blob: 6997788389a2fbd9baaa1ad8859aac8d6cd5798a [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07002 * Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
George Gao3018ede2019-10-23 13:23:00 -070047#include <limits.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080048#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080072#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070096#define INVALID_OUT_VOLUME -1
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070097#define AUDIO_IO_PORTS_MAX 32
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070098
Aalique Grahame22e49102018-12-18 14:23:57 -080099#define RECORD_GAIN_MIN 0.0f
100#define RECORD_GAIN_MAX 1.0f
101#define RECORD_VOLUME_CTL_MAX 0x2000
102
103/* treat as unsigned Q1.13 */
104#define APP_TYPE_GAIN_DEFAULT 0x2000
105
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700106#define PROXY_OPEN_RETRY_COUNT 100
107#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800108
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800109#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
110 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
111 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
112#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
113 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800114
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700115#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700116#define DEFAULT_VOIP_BUF_DURATION_MS 20
117#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
118#define DEFAULT_VOIP_SAMP_RATE 48000
119
120#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
121
122struct pcm_config default_pcm_config_voip_copp = {
123 .channels = 1,
124 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
125 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
126 .period_count = 2,
127 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800128 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
129 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700130};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700131
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700132#define MIN_CHANNEL_COUNT 1
133#define DEFAULT_CHANNEL_COUNT 2
134#define MAX_HIFI_CHANNEL_COUNT 8
135
Aalique Grahame22e49102018-12-18 14:23:57 -0800136#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
137#define MAX_CHANNEL_COUNT 1
138#else
139#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
140#define XSTR(x) STR(x)
141#define STR(x) #x
142#endif
143
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700144static unsigned int configured_low_latency_capture_period_size =
145 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
146
Haynes Mathew George16081042017-05-31 17:16:49 -0700147#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
148#define MMAP_PERIOD_COUNT_MIN 32
149#define MMAP_PERIOD_COUNT_MAX 512
150#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
151
Aalique Grahame22e49102018-12-18 14:23:57 -0800152/* This constant enables extended precision handling.
153 * TODO The flag is off until more testing is done.
154 */
155static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700156extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800157
Eric Laurentb23d5282013-05-14 15:27:20 -0700158struct pcm_config pcm_config_deep_buffer = {
159 .channels = 2,
160 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
161 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
162 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
163 .format = PCM_FORMAT_S16_LE,
164 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
165 .stop_threshold = INT_MAX,
166 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
167};
168
169struct pcm_config pcm_config_low_latency = {
170 .channels = 2,
171 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
172 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
173 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
174 .format = PCM_FORMAT_S16_LE,
175 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
176 .stop_threshold = INT_MAX,
177 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
178};
179
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800180struct pcm_config pcm_config_haptics_audio = {
181 .channels = 1,
182 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
183 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
184 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
185 .format = PCM_FORMAT_S16_LE,
186 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
187 .stop_threshold = INT_MAX,
188 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
189};
190
191struct pcm_config pcm_config_haptics = {
192 .channels = 1,
193 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
194 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
195 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
196 .format = PCM_FORMAT_S16_LE,
197 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
198 .stop_threshold = INT_MAX,
199 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
200};
201
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700202static int af_period_multiplier = 4;
203struct pcm_config pcm_config_rt = {
204 .channels = 2,
205 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
206 .period_size = ULL_PERIOD_SIZE, //1 ms
207 .period_count = 512, //=> buffer size is 512ms
208 .format = PCM_FORMAT_S16_LE,
209 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
210 .stop_threshold = INT_MAX,
211 .silence_threshold = 0,
212 .silence_size = 0,
213 .avail_min = ULL_PERIOD_SIZE, //1 ms
214};
215
Eric Laurentb23d5282013-05-14 15:27:20 -0700216struct pcm_config pcm_config_hdmi_multi = {
217 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
218 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
219 .period_size = HDMI_MULTI_PERIOD_SIZE,
220 .period_count = HDMI_MULTI_PERIOD_COUNT,
221 .format = PCM_FORMAT_S16_LE,
222 .start_threshold = 0,
223 .stop_threshold = INT_MAX,
224 .avail_min = 0,
225};
226
Haynes Mathew George16081042017-05-31 17:16:49 -0700227struct pcm_config pcm_config_mmap_playback = {
228 .channels = 2,
229 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
230 .period_size = MMAP_PERIOD_SIZE,
231 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
232 .format = PCM_FORMAT_S16_LE,
233 .start_threshold = MMAP_PERIOD_SIZE*8,
234 .stop_threshold = INT32_MAX,
235 .silence_threshold = 0,
236 .silence_size = 0,
237 .avail_min = MMAP_PERIOD_SIZE, //1 ms
238};
239
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700240struct pcm_config pcm_config_hifi = {
241 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
242 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
243 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
244 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
245 .format = PCM_FORMAT_S24_3LE,
246 .start_threshold = 0,
247 .stop_threshold = INT_MAX,
248 .avail_min = 0,
249};
250
Eric Laurentb23d5282013-05-14 15:27:20 -0700251struct pcm_config pcm_config_audio_capture = {
252 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700253 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
254 .format = PCM_FORMAT_S16_LE,
255};
256
Haynes Mathew George16081042017-05-31 17:16:49 -0700257struct pcm_config pcm_config_mmap_capture = {
258 .channels = 2,
259 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
260 .period_size = MMAP_PERIOD_SIZE,
261 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
262 .format = PCM_FORMAT_S16_LE,
263 .start_threshold = 0,
264 .stop_threshold = INT_MAX,
265 .silence_threshold = 0,
266 .silence_size = 0,
267 .avail_min = MMAP_PERIOD_SIZE, //1 ms
268};
269
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700270#define AFE_PROXY_CHANNEL_COUNT 2
271#define AFE_PROXY_SAMPLING_RATE 48000
272
273#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
274#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
275
276struct pcm_config pcm_config_afe_proxy_playback = {
277 .channels = AFE_PROXY_CHANNEL_COUNT,
278 .rate = AFE_PROXY_SAMPLING_RATE,
279 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
280 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
281 .format = PCM_FORMAT_S16_LE,
282 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
283 .stop_threshold = INT_MAX,
284 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
285};
286
287#define AFE_PROXY_RECORD_PERIOD_SIZE 768
288#define AFE_PROXY_RECORD_PERIOD_COUNT 4
289
Aalique Grahame22e49102018-12-18 14:23:57 -0800290struct pcm_config pcm_config_audio_capture_rt = {
291 .channels = 2,
292 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
293 .period_size = ULL_PERIOD_SIZE,
294 .period_count = 512,
295 .format = PCM_FORMAT_S16_LE,
296 .start_threshold = 0,
297 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
298 .silence_threshold = 0,
299 .silence_size = 0,
300 .avail_min = ULL_PERIOD_SIZE, //1 ms
301};
302
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700303struct pcm_config pcm_config_afe_proxy_record = {
304 .channels = AFE_PROXY_CHANNEL_COUNT,
305 .rate = AFE_PROXY_SAMPLING_RATE,
306 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
307 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
308 .format = PCM_FORMAT_S16_LE,
309 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
310 .stop_threshold = INT_MAX,
311 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
312};
313
Ashish Jainf1eaa582016-05-23 20:54:24 +0530314#define AUDIO_MAX_PCM_FORMATS 7
315
316const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
317 [AUDIO_FORMAT_DEFAULT] = 0,
318 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
319 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
320 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
321 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
322 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
323 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
324};
325
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800326const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700327 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
328 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800329 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700330 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
331 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700332 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700333 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700334 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
341 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700342 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
343 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700344 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800345 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700346
Eric Laurentb23d5282013-05-14 15:27:20 -0700347 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700348 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530349 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
350 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
351 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530352 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
353 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700354 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700355 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700356 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700357 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700358
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800359 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800360 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Derek Chenf7092792017-05-23 12:23:53 -0400361 [USECASE_AUDIO_HFP_SCO_DOWNLINK] = "hfp-sco-downlink",
362 [USECASE_AUDIO_HFP_SCO_WB_DOWNLINK] = "hfp-sco-wb-downlink",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700363
Derek Chenf7092792017-05-23 12:23:53 -0400364 [USECASE_VOICE_CALL] = "voice-call",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700365 [USECASE_VOICE2_CALL] = "voice2-call",
366 [USECASE_VOLTE_CALL] = "volte-call",
367 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800368 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800369 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
370 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800371 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700372 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
373 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
374 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800375 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
376 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
377 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
378
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700379 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
380 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700381 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
382 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700383
384 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
385 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530386 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700387
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530388 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530389 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
390 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700391
392 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
393 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530394 /* For Interactive Audio Streams */
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
400 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
401 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
402 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700403
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800404 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
405
Derek Chenf6318be2017-06-12 17:16:24 -0400406 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
407
408 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
409 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
410 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
411 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Derek Chendf05eea2019-08-01 13:57:49 -0700412 [USECASE_AUDIO_PLAYBACK_REAR_SEAT] = "rear-seat-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530413 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700414};
415
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700416static const audio_usecase_t offload_usecases[] = {
417 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700418 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
419 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
422 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
423 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
424 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
425 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700426};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800427
Varun Balaraje49253e2017-07-06 19:48:56 +0530428static const audio_usecase_t interactive_usecases[] = {
429 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
433 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
434 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
435 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
436 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
437};
438
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800439#define STRING_TO_ENUM(string) { #string, string }
440
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800441struct string_to_enum {
442 const char *name;
443 uint32_t value;
444};
445
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700446static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800447 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700451 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800452 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
453 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800454 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700455 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
456 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
457 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
458 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
462 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
463 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
464 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
465 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800466};
467
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700468static const struct string_to_enum formats_name_to_enum_table[] = {
469 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
470 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
471 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700472 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
473 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
474 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700475 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800476 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
477 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700478 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800479};
480
481//list of all supported sample rates by HDMI specification.
482static const int out_hdmi_sample_rates[] = {
483 32000, 44100, 48000, 88200, 96000, 176400, 192000,
484};
485
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700486static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800487 STRING_TO_ENUM(32000),
488 STRING_TO_ENUM(44100),
489 STRING_TO_ENUM(48000),
490 STRING_TO_ENUM(88200),
491 STRING_TO_ENUM(96000),
492 STRING_TO_ENUM(176400),
493 STRING_TO_ENUM(192000),
Mingshu pange8aedf12019-10-25 15:38:27 +0800494 STRING_TO_ENUM(352800),
495 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700496};
497
Carter Hsu2e429db2019-05-14 18:50:52 +0800498struct in_effect_list {
499 struct listnode list;
500 effect_handle_t handle;
501};
502
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700503static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700504static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700505static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700506//cache last MBDRC cal step level
507static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700508
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530509static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
510static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700511static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800512static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530513static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530514
Derek Chen6f293672019-04-01 01:40:24 -0700515static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
516static void in_snd_mon_cb(void * stream, struct str_parms * parms);
517static void out_snd_mon_cb(void * stream, struct str_parms * parms);
518
Zhou Song331c8e52019-08-26 14:16:12 +0800519static int configure_btsco_sample_rate(snd_device_t snd_device);
520
Vatsal Buchac09ae062018-11-14 13:25:08 +0530521#ifdef AUDIO_FEATURE_ENABLED_GCOV
522extern void __gcov_flush();
523static void enable_gcov()
524{
525 __gcov_flush();
526}
527#else
528static void enable_gcov()
529{
530}
531#endif
532
justinweng20fb6d82019-02-21 18:49:00 -0700533static int in_set_microphone_direction(const struct audio_stream_in *stream,
534 audio_microphone_direction_t dir);
535static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
536
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700537static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
538 int flags __unused)
539{
540 int dir = 0;
541 switch (uc_id) {
542 case USECASE_AUDIO_RECORD_LOW_LATENCY:
543 dir = 1;
544 case USECASE_AUDIO_PLAYBACK_ULL:
545 break;
546 default:
547 return false;
548 }
549
550 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
551 PCM_PLAYBACK : PCM_CAPTURE);
552 if (adev->adm_is_noirq_avail)
553 return adev->adm_is_noirq_avail(adev->adm_data,
554 adev->snd_card, dev_id, dir);
555 return false;
556}
557
558static void register_out_stream(struct stream_out *out)
559{
560 struct audio_device *adev = out->dev;
561 if (is_offload_usecase(out->usecase) ||
562 !adev->adm_register_output_stream)
563 return;
564
565 // register stream first for backward compatibility
566 adev->adm_register_output_stream(adev->adm_data,
567 out->handle,
568 out->flags);
569
570 if (!adev->adm_set_config)
571 return;
572
573 if (out->realtime)
574 adev->adm_set_config(adev->adm_data,
575 out->handle,
576 out->pcm, &out->config);
577}
578
579static void register_in_stream(struct stream_in *in)
580{
581 struct audio_device *adev = in->dev;
582 if (!adev->adm_register_input_stream)
583 return;
584
585 adev->adm_register_input_stream(adev->adm_data,
586 in->capture_handle,
587 in->flags);
588
589 if (!adev->adm_set_config)
590 return;
591
592 if (in->realtime)
593 adev->adm_set_config(adev->adm_data,
594 in->capture_handle,
595 in->pcm,
596 &in->config);
597}
598
599static void request_out_focus(struct stream_out *out, long ns)
600{
601 struct audio_device *adev = out->dev;
602
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700603 if (adev->adm_request_focus_v2)
604 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
605 else if (adev->adm_request_focus)
606 adev->adm_request_focus(adev->adm_data, out->handle);
607}
608
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700609static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700610{
611 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700612 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700613
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700614 if (adev->adm_request_focus_v2_1)
615 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
616 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700617 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
618 else if (adev->adm_request_focus)
619 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700620
621 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700622}
623
624static void release_out_focus(struct stream_out *out)
625{
626 struct audio_device *adev = out->dev;
627
628 if (adev->adm_abandon_focus)
629 adev->adm_abandon_focus(adev->adm_data, out->handle);
630}
631
632static void release_in_focus(struct stream_in *in)
633{
634 struct audio_device *adev = in->dev;
635 if (adev->adm_abandon_focus)
636 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
637}
638
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530639static int parse_snd_card_status(struct str_parms *parms, int *card,
640 card_status_t *status)
641{
642 char value[32]={0};
643 char state[32]={0};
644
645 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
646 if (ret < 0)
647 return -1;
648
649 // sscanf should be okay as value is of max length 32.
650 // same as sizeof state.
651 if (sscanf(value, "%d,%s", card, state) < 2)
652 return -1;
653
654 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
655 CARD_STATUS_OFFLINE;
656 return 0;
657}
658
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700659static inline void adjust_frames_for_device_delay(struct stream_out *out,
660 uint32_t *dsp_frames) {
661 // Adjustment accounts for A2dp encoder latency with offload usecases
662 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -0800663 if (is_a2dp_out_device_type(&out->device_list)) {
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700664 unsigned long offset =
665 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
666 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
667 }
668}
669
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700670static inline bool free_entry(void *key __unused,
671 void *value, void *context __unused)
672{
673 free(value);
674 return true;
675}
676
677static inline void free_map(Hashmap *map)
678{
679 if (map) {
680 hashmapForEach(map, free_entry, (void *) NULL);
681 hashmapFree(map);
682 }
683}
684
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800685static inline void patch_map_remove_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700686 audio_patch_handle_t patch_handle)
687{
688 if (patch_handle == AUDIO_PATCH_HANDLE_NONE)
689 return;
690
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700691 struct audio_patch_info *p_info =
692 hashmapGet(adev->patch_map, (void *) (intptr_t) patch_handle);
693 if (p_info) {
694 ALOGV("%s: Remove patch %d", __func__, patch_handle);
695 hashmapRemove(adev->patch_map, (void *) (intptr_t) patch_handle);
696 free(p_info->patch);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700697 free(p_info);
698 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700699}
700
701static inline int io_streams_map_insert(struct audio_device *adev,
702 struct audio_stream *stream,
703 audio_io_handle_t handle,
704 audio_patch_handle_t patch_handle)
705{
706 struct audio_stream_info *s_info =
707 (struct audio_stream_info *) calloc(1, sizeof(struct audio_stream_info));
708
709 if (s_info == NULL) {
710 ALOGE("%s: Could not allocate stream info", __func__);
711 return -ENOMEM;
712 }
713 s_info->stream = stream;
714 s_info->patch_handle = patch_handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700715
716 pthread_mutex_lock(&adev->lock);
717 struct audio_stream_info *stream_info =
718 hashmapPut(adev->io_streams_map, (void *) (intptr_t) handle, (void *) s_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700719 if (stream_info != NULL)
720 free(stream_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800721 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700722 ALOGD("%s: Added stream in io_streams_map with handle %d", __func__, handle);
723 return 0;
724}
725
726static inline void io_streams_map_remove(struct audio_device *adev,
727 audio_io_handle_t handle)
728{
729 pthread_mutex_lock(&adev->lock);
730 struct audio_stream_info *s_info =
731 hashmapRemove(adev->io_streams_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700732 if (s_info == NULL)
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800733 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700734 ALOGD("%s: Removed stream with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800735 patch_map_remove_l(adev, s_info->patch_handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700736 free(s_info);
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800737done:
738 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700739 return;
740}
741
Aniket Kumar Latabc774842020-01-16 21:22:05 -0800742static struct audio_patch_info* fetch_patch_info_l(struct audio_device *adev,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700743 audio_patch_handle_t handle)
744{
745 struct audio_patch_info *p_info = NULL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700746 p_info = (struct audio_patch_info *)
747 hashmapGet(adev->patch_map, (void *) (intptr_t) handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -0700748 return p_info;
749}
750
vivek mehtaa76401a2015-04-24 14:12:15 -0700751__attribute__ ((visibility ("default")))
752bool audio_hw_send_gain_dep_calibration(int level) {
753 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700754 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700755
756 pthread_mutex_lock(&adev_init_lock);
757
758 if (adev != NULL && adev->platform != NULL) {
759 pthread_mutex_lock(&adev->lock);
760 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700761
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530762 // cache level info for any of the use case which
763 // was not started.
764 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700765
vivek mehtaa76401a2015-04-24 14:12:15 -0700766 pthread_mutex_unlock(&adev->lock);
767 } else {
768 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
769 }
770
771 pthread_mutex_unlock(&adev_init_lock);
772
773 return ret_val;
774}
775
Ashish Jain5106d362016-05-11 19:23:33 +0530776static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
777{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800778 bool gapless_enabled = false;
779 const char *mixer_ctl_name = "Compress Gapless Playback";
780 struct mixer_ctl *ctl;
781
782 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700783 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530784
785 /*Disable gapless if its AV playback*/
786 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800787
788 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
789 if (!ctl) {
790 ALOGE("%s: Could not get ctl for mixer cmd - %s",
791 __func__, mixer_ctl_name);
792 return -EINVAL;
793 }
794
795 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
796 ALOGE("%s: Could not set gapless mode %d",
797 __func__, gapless_enabled);
798 return -EINVAL;
799 }
800 return 0;
801}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700802
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700803__attribute__ ((visibility ("default")))
804int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
805 int table_size) {
806 int ret_val = 0;
807 ALOGV("%s: enter ... ", __func__);
808
809 pthread_mutex_lock(&adev_init_lock);
810 if (adev == NULL) {
811 ALOGW("%s: adev is NULL .... ", __func__);
812 goto done;
813 }
814
815 pthread_mutex_lock(&adev->lock);
816 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
817 pthread_mutex_unlock(&adev->lock);
818done:
819 pthread_mutex_unlock(&adev_init_lock);
820 ALOGV("%s: exit ... ", __func__);
821 return ret_val;
822}
823
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800824bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800825{
826 bool ret = false;
827 ALOGV("%s: enter ...", __func__);
828
829 pthread_mutex_lock(&adev_init_lock);
830
831 if (adev != NULL && adev->platform != NULL) {
832 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800833 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800834 pthread_mutex_unlock(&adev->lock);
835 }
836
837 pthread_mutex_unlock(&adev_init_lock);
838
839 ALOGV("%s: exit with ret %d", __func__, ret);
840 return ret;
841}
Aalique Grahame22e49102018-12-18 14:23:57 -0800842
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700843static bool is_supported_format(audio_format_t format)
844{
Eric Laurent86e17132013-09-12 17:49:30 -0700845 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530846 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530847 format == AUDIO_FORMAT_AAC_LC ||
848 format == AUDIO_FORMAT_AAC_HE_V1 ||
849 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530850 format == AUDIO_FORMAT_AAC_ADTS_LC ||
851 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
852 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530853 format == AUDIO_FORMAT_AAC_LATM_LC ||
854 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
855 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530856 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
857 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530858 format == AUDIO_FORMAT_PCM_FLOAT ||
859 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700860 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530861 format == AUDIO_FORMAT_AC3 ||
862 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700863 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530864 format == AUDIO_FORMAT_DTS ||
865 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800866 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530867 format == AUDIO_FORMAT_ALAC ||
868 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530869 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530870 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800871 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530872 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700873 format == AUDIO_FORMAT_APTX ||
874 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800875 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700876
877 return false;
878}
879
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700880static inline bool is_mmap_usecase(audio_usecase_t uc_id)
881{
882 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
883 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
884}
885
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700886static inline bool is_valid_volume(float left, float right)
887{
888 return ((left >= 0.0f && right >= 0.0f) ? true : false);
889}
890
Avinash Vaish71a8b972014-07-24 15:36:33 +0530891static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
892 struct audio_usecase *uc_info)
893{
894 struct listnode *node;
895 struct audio_usecase *usecase;
896
897 if (uc_info == NULL)
898 return -EINVAL;
899
900 /* Re-route all voice usecases on the shared backend other than the
901 specified usecase to new snd devices */
902 list_for_each(node, &adev->usecase_list) {
903 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800904 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530905 enable_audio_route(adev, usecase);
906 }
907 return 0;
908}
909
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530910static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530911{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530912 ALOGV("%s", __func__);
913 audio_route_apply_and_update_path(adev->audio_route,
914 "asrc-mode");
915 adev->asrc_mode_enabled = true;
916}
917
918static void disable_asrc_mode(struct audio_device *adev)
919{
920 ALOGV("%s", __func__);
921 audio_route_reset_and_update_path(adev->audio_route,
922 "asrc-mode");
923 adev->asrc_mode_enabled = false;
924}
925
926/*
927 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
928 * 44.1 or Native DSD backends are enabled for any of current use case.
929 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
930 * - Disable current mix path use case(Headphone backend) and re-enable it with
931 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
932 * e.g. Naitve DSD or Headphone 44.1 -> + 48
933 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530934static void check_and_set_asrc_mode(struct audio_device *adev,
935 struct audio_usecase *uc_info,
936 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530937{
938 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530939 int i, num_new_devices = 0;
940 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
941 /*
942 *Split snd device for new combo use case
943 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
944 */
945 if (platform_split_snd_device(adev->platform,
946 snd_device,
947 &num_new_devices,
948 split_new_snd_devices) == 0) {
949 for (i = 0; i < num_new_devices; i++)
950 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
951 } else {
952 int new_backend_idx = platform_get_backend_index(snd_device);
953 if (((new_backend_idx == HEADPHONE_BACKEND) ||
954 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
955 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
956 !adev->asrc_mode_enabled) {
957 struct listnode *node = NULL;
958 struct audio_usecase *uc = NULL;
959 struct stream_out *curr_out = NULL;
960 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
961 int i, num_devices, ret = 0;
962 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530963
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530964 list_for_each(node, &adev->usecase_list) {
965 uc = node_to_item(node, struct audio_usecase, list);
966 curr_out = (struct stream_out*) uc->stream.out;
967 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
968 /*
969 *Split snd device for existing combo use case
970 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
971 */
972 ret = platform_split_snd_device(adev->platform,
973 uc->out_snd_device,
974 &num_devices,
975 split_snd_devices);
976 if (ret < 0 || num_devices == 0) {
977 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
978 split_snd_devices[0] = uc->out_snd_device;
979 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800980 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530981 for (i = 0; i < num_devices; i++) {
982 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
983 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
984 if((new_backend_idx == HEADPHONE_BACKEND) &&
985 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
986 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
987 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
988 __func__);
989 enable_asrc_mode(adev);
990 break;
991 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
992 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
993 (usecase_backend_idx == HEADPHONE_BACKEND)) {
994 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
995 __func__);
996 disable_audio_route(adev, uc);
997 disable_snd_device(adev, uc->out_snd_device);
998 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
999 if (new_backend_idx == DSD_NATIVE_BACKEND)
1000 audio_route_apply_and_update_path(adev->audio_route,
1001 "hph-true-highquality-mode");
1002 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
1003 (curr_out->bit_width >= 24))
1004 audio_route_apply_and_update_path(adev->audio_route,
1005 "hph-highquality-mode");
1006 enable_asrc_mode(adev);
1007 enable_snd_device(adev, uc->out_snd_device);
1008 enable_audio_route(adev, uc);
1009 break;
1010 }
1011 }
1012 // reset split devices count
1013 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -08001014 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05301015 if (adev->asrc_mode_enabled)
1016 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301017 }
1018 }
1019 }
1020}
1021
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001022static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
1023 struct audio_effect_config effect_config,
1024 unsigned int param_value)
1025{
1026 char mixer_ctl_name[] = "Audio Effect";
1027 struct mixer_ctl *ctl;
1028 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -08001029 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001030
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001031 if (in == NULL) {
1032 ALOGE("%s: active input stream is NULL", __func__);
1033 return -EINVAL;
1034 }
1035
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001036 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
1037 if (!ctl) {
1038 ALOGE("%s: Could not get mixer ctl - %s",
1039 __func__, mixer_ctl_name);
1040 return -EINVAL;
1041 }
1042
1043 set_values[0] = 1; //0:Rx 1:Tx
1044 set_values[1] = in->app_type_cfg.app_type;
1045 set_values[2] = (long)effect_config.module_id;
1046 set_values[3] = (long)effect_config.instance_id;
1047 set_values[4] = (long)effect_config.param_id;
1048 set_values[5] = param_value;
1049
1050 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
1051
1052 return 0;
1053
1054}
1055
1056static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
1057 int effect_type, unsigned int *param_value)
1058{
1059 int ret = 0;
1060 struct audio_effect_config other_effect_config;
1061 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08001062 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001063
Aniket Kumar Lata7de63522019-06-13 11:05:18 -07001064 if (in == NULL) {
1065 ALOGE("%s: active input stream is NULL", __func__);
1066 return -EINVAL;
1067 }
1068
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001069 usecase = get_usecase_from_list(adev, in->usecase);
1070 if (!usecase)
1071 return -EINVAL;
1072
1073 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
1074 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
1075 if (ret < 0) {
1076 ALOGE("%s Failed to get effect params %d", __func__, ret);
1077 return ret;
1078 }
1079
1080 if (module_id == other_effect_config.module_id) {
1081 //Same module id for AEC/NS. Values need to be combined
1082 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
1083 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
1084 *param_value |= other_effect_config.param_value;
1085 }
1086 }
1087
1088 return ret;
1089}
1090
1091static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301092{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001093 struct audio_effect_config effect_config;
1094 struct audio_usecase *usecase = NULL;
1095 int ret = 0;
1096 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001097 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001098
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001099 if(!voice_extn_is_dynamic_ecns_enabled())
1100 return ENOSYS;
1101
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001102 if (!in) {
1103 ALOGE("%s: Invalid input stream", __func__);
1104 return -EINVAL;
1105 }
1106
1107 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1108
1109 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001110 if (usecase == NULL) {
1111 ALOGE("%s: Could not find the usecase (%d) in the list",
1112 __func__, in->usecase);
1113 return -EINVAL;
1114 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001115
1116 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1117 if (ret < 0) {
1118 ALOGE("%s Failed to get module id %d", __func__, ret);
1119 return ret;
1120 }
1121 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1122 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1123
1124 if(enable)
1125 param_value = effect_config.param_value;
1126
1127 /*Special handling for AEC & NS effects Param values need to be
1128 updated if module ids are same*/
1129
1130 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1131 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1132 if (ret < 0)
1133 return ret;
1134 }
1135
1136 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1137
1138 return ret;
1139}
1140
1141static void check_and_enable_effect(struct audio_device *adev)
1142{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001143 if(!voice_extn_is_dynamic_ecns_enabled())
1144 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001145
Eric Laurent637e2d42018-11-15 12:24:31 -08001146 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001147
Eric Laurent637e2d42018-11-15 12:24:31 -08001148 if (in != NULL && !in->standby) {
1149 if (in->enable_aec)
1150 enable_disable_effect(adev, EFFECT_AEC, true);
1151
1152 if (in->enable_ns &&
1153 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1154 enable_disable_effect(adev, EFFECT_NS, true);
1155 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001156 }
1157}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001158
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001159int pcm_ioctl(struct pcm *pcm, int request, ...)
1160{
1161 va_list ap;
1162 void * arg;
1163 int pcm_fd = *(int*)pcm;
1164
1165 va_start(ap, request);
1166 arg = va_arg(ap, void *);
1167 va_end(ap);
1168
1169 return ioctl(pcm_fd, request, arg);
1170}
1171
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001172int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001173 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001174{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001175 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001176 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301177 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301178 struct stream_in *in = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001179 struct listnode out_devices;
Soumya Managoli6993b762018-06-28 16:04:57 +05301180 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001181
1182 if (usecase == NULL)
1183 return -EINVAL;
1184
1185 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1186
Carter Hsu2e429db2019-05-14 18:50:52 +08001187 if (usecase->type == PCM_CAPTURE) {
1188 struct stream_in *in = usecase->stream.in;
1189 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001190 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001191
1192 if (in) {
1193 if (in->enable_aec || in->enable_ec_port) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001194 list_init(&out_devices);
1195 update_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "", true);
Carter Hsu2e429db2019-05-14 18:50:52 +08001196 struct listnode *node;
1197 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1198 USECASE_AUDIO_PLAYBACK_VOIP);
1199 if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001200 assign_devices(&out_devices,
1201 &voip_usecase->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001202 } else if (adev->primary_output &&
1203 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001204 assign_devices(&out_devices,
1205 &adev->primary_output->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001206 } else {
1207 list_for_each(node, &adev->usecase_list) {
1208 uinfo = node_to_item(node, struct audio_usecase, list);
1209 if (uinfo->type != PCM_CAPTURE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001210 assign_devices(&out_devices,
1211 &uinfo->stream.out->device_list);
Carter Hsu2e429db2019-05-14 18:50:52 +08001212 break;
1213 }
1214 }
1215 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001216
1217 platform_set_echo_reference(adev, true, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001218 in->ec_opened = true;
1219 }
1220 }
Guodong Huf5e614d2019-06-24 18:42:03 +08001221 } else if ((usecase->type == TRANSCODE_LOOPBACK_TX) || ((usecase->type == PCM_HFP_CALL) &&
1222 ((usecase->id == USECASE_AUDIO_HFP_SCO) || (usecase->id == USECASE_AUDIO_HFP_SCO_WB)) &&
1223 (usecase->in_snd_device == SND_DEVICE_IN_VOICE_SPEAKER_MIC_HFP_MMSECNS))) {
Carter Hsu2e429db2019-05-14 18:50:52 +08001224 snd_device = usecase->in_snd_device;
1225 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001226 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001227 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001228
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001229#ifdef DS1_DOLBY_DAP_ENABLED
1230 audio_extn_dolby_set_dmid(adev);
1231 audio_extn_dolby_set_endpoint(adev);
1232#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001233 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001234 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301235 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001236 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001237 if (audio_extn_is_maxx_audio_enabled())
1238 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301239 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301240 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1241 out = usecase->stream.out;
1242 if (out && out->compr)
1243 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1244 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301245
1246 if (usecase->type == PCM_CAPTURE) {
1247 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001248 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301249 ALOGD("%s: set custom mtmx params v1", __func__);
1250 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1251 }
1252 } else {
1253 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1254 }
Manish Dewangan58229382017-02-02 15:48:41 +05301255
Andy Hung756ecc12018-10-19 17:47:12 -07001256 // we shouldn't truncate mixer_path
1257 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1258 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1259 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001260 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001261 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301262 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1263 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1264 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1265 if (parms) {
1266 audio_extn_fm_set_parameters(adev, parms);
1267 str_parms_destroy(parms);
1268 }
1269 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001270 ALOGV("%s: exit", __func__);
1271 return 0;
1272}
1273
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001274int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001275 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001276{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001277 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001278 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301279 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001280
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301281 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001282 return -EINVAL;
1283
1284 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301285 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001286 snd_device = usecase->in_snd_device;
1287 else
1288 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001289 // we shouldn't truncate mixer_path
1290 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1291 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1292 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001293 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001294 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001295 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001296 if (usecase->type == PCM_CAPTURE) {
1297 struct stream_in *in = usecase->stream.in;
1298 if (in && in->ec_opened) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001299 struct listnode out_devices;
1300 list_init(&out_devices);
1301 platform_set_echo_reference(in->dev, false, &out_devices);
Carter Hsu2e429db2019-05-14 18:50:52 +08001302 in->ec_opened = false;
1303 }
1304 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001305 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301306 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301307
1308 if (usecase->type == PCM_CAPTURE) {
1309 in = usecase->stream.in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001310 if (in && is_loopback_input_device(get_device_types(&in->device_list))) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301311 ALOGD("%s: reset custom mtmx params v1", __func__);
1312 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1313 }
1314 } else {
1315 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1316 }
1317
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001318 if ((usecase->type == PCM_PLAYBACK) &&
1319 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301320 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001322 ALOGV("%s: exit", __func__);
1323 return 0;
1324}
1325
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001326int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001327 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001328{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301329 int i, num_devices = 0;
1330 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001331 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1332
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001333 if (snd_device < SND_DEVICE_MIN ||
1334 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001335 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001336 return -EINVAL;
1337 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001338
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001339 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001340 ALOGE("%s: Invalid sound device returned", __func__);
1341 return -EINVAL;
1342 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001343
1344 adev->snd_dev_ref_cnt[snd_device]++;
1345
1346 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1347 (platform_split_snd_device(adev->platform,
1348 snd_device,
1349 &num_devices,
1350 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001351 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001352 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001353 return 0;
1354 }
1355
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001356 if (audio_extn_spkr_prot_is_enabled())
1357 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001358
Aalique Grahame22e49102018-12-18 14:23:57 -08001359 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1360
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001361 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1362 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001363 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1364 goto err;
1365 }
1366 audio_extn_dev_arbi_acquire(snd_device);
1367 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001368 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001369 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001370 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001371 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001372 } else if (platform_split_snd_device(adev->platform,
1373 snd_device,
1374 &num_devices,
1375 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301376 for (i = 0; i < num_devices; i++) {
1377 enable_snd_device(adev, new_snd_devices[i]);
1378 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001379 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001380 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001381 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301382
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301383
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001384 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1385 (audio_extn_a2dp_start_playback() < 0)) {
1386 ALOGE(" fail to configure A2dp Source control path ");
1387 goto err;
1388 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001389
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001390 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1391 (audio_extn_a2dp_start_capture() < 0)) {
1392 ALOGE(" fail to configure A2dp Sink control path ");
1393 goto err;
1394 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301395
Mingshu Pang7be5b1d2020-03-04 15:24:38 +08001396 if ((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1397 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1398 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) {
1399 if (!adev->bt_sco_on || (audio_extn_sco_start_configuration() < 0)) {
1400 ALOGE(" fail to configure sco control path ");
1401 goto err;
1402 }
Zhou Song12c29502019-03-16 10:37:18 +08001403 }
1404
Zhou Song331c8e52019-08-26 14:16:12 +08001405 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001406 /* due to the possibility of calibration overwrite between listen
1407 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001408 audio_extn_sound_trigger_update_device_status(snd_device,
1409 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301410 audio_extn_listen_update_device_status(snd_device,
1411 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001412 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001413 audio_extn_sound_trigger_update_device_status(snd_device,
1414 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301415 audio_extn_listen_update_device_status(snd_device,
1416 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001417 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001418 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001419 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001420 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301421
1422 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1423 !adev->native_playback_enabled &&
1424 audio_is_true_native_stream_active(adev)) {
1425 ALOGD("%s: %d: napb: enabling native mode in hardware",
1426 __func__, __LINE__);
1427 audio_route_apply_and_update_path(adev->audio_route,
1428 "true-native-mode");
1429 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301430 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301431 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1432 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001433 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001434 ALOGD("%s: init ec ref loopback", __func__);
1435 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1436 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001437 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001438 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001439err:
1440 adev->snd_dev_ref_cnt[snd_device]--;
1441 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001442}
1443
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001444int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001445 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001446{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301447 int i, num_devices = 0;
1448 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001449 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1450
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001451 if (snd_device < SND_DEVICE_MIN ||
1452 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001453 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001454 return -EINVAL;
1455 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001456
1457 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1458 ALOGE("%s: Invalid sound device returned", __func__);
1459 return -EINVAL;
1460 }
1461
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1463 ALOGE("%s: device ref cnt is already 0", __func__);
1464 return -EINVAL;
1465 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001466
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001467 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001468
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001469
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001470 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001471 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301472
Aalique Grahame22e49102018-12-18 14:23:57 -08001473 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1474
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001475 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1476 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001477 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001478
1479 // when speaker device is disabled, reset swap.
1480 // will be renabled on usecase start
1481 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001482 } else if (platform_split_snd_device(adev->platform,
1483 snd_device,
1484 &num_devices,
1485 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301486 for (i = 0; i < num_devices; i++) {
1487 disable_snd_device(adev, new_snd_devices[i]);
1488 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001489 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001490 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001491 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001492 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001493
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001494 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301495 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001496 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001497 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001498 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001499 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301500 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001501 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301502 adev->native_playback_enabled) {
1503 ALOGD("%s: %d: napb: disabling native mode in hardware",
1504 __func__, __LINE__);
1505 audio_route_reset_and_update_path(adev->audio_route,
1506 "true-native-mode");
1507 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001508 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301509 adev->asrc_mode_enabled) {
1510 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301511 disable_asrc_mode(adev);
1512 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001513 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301514 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001515 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001516 ALOGD("%s: deinit ec ref loopback", __func__);
1517 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1518 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001519
1520 audio_extn_utils_release_snd_device(snd_device);
1521 } else {
1522 if (platform_split_snd_device(adev->platform,
1523 snd_device,
1524 &num_devices,
1525 new_snd_devices) == 0) {
1526 for (i = 0; i < num_devices; i++) {
1527 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1528 }
1529 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001530 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001532 return 0;
1533}
1534
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001535/*
1536 legend:
1537 uc - existing usecase
1538 new_uc - new usecase
1539 d1, d11, d2 - SND_DEVICE enums
1540 a1, a2 - corresponding ANDROID device enums
1541 B1, B2 - backend strings
1542
1543case 1
1544 uc->dev d1 (a1) B1
1545 new_uc->dev d1 (a1), d2 (a2) B1, B2
1546
1547 resolution: disable and enable uc->dev on d1
1548
1549case 2
1550 uc->dev d1 (a1) B1
1551 new_uc->dev d11 (a1) B1
1552
1553 resolution: need to switch uc since d1 and d11 are related
1554 (e.g. speaker and voice-speaker)
1555 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1556
1557case 3
1558 uc->dev d1 (a1) B1
1559 new_uc->dev d2 (a2) B2
1560
1561 resolution: no need to switch uc
1562
1563case 4
1564 uc->dev d1 (a1) B1
1565 new_uc->dev d2 (a2) B1
1566
1567 resolution: disable enable uc-dev on d2 since backends match
1568 we cannot enable two streams on two different devices if they
1569 share the same backend. e.g. if offload is on speaker device using
1570 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1571 using the same backend, offload must also be switched to voice-handset.
1572
1573case 5
1574 uc->dev d1 (a1) B1
1575 new_uc->dev d1 (a1), d2 (a2) B1
1576
1577 resolution: disable enable uc-dev on d2 since backends match
1578 we cannot enable two streams on two different devices if they
1579 share the same backend.
1580
1581case 6
1582 uc->dev d1 (a1) B1
1583 new_uc->dev d2 (a1) B2
1584
1585 resolution: no need to switch
1586
1587case 7
1588 uc->dev d1 (a1), d2 (a2) B1, B2
1589 new_uc->dev d1 (a1) B1
1590
1591 resolution: no need to switch
1592
Zhou Song4ba65882018-07-09 14:48:07 +08001593case 8
1594 uc->dev d1 (a1) B1
1595 new_uc->dev d11 (a1), d2 (a2) B1, B2
1596 resolution: compared to case 1, for this case, d1 and d11 are related
1597 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001598*/
1599static snd_device_t derive_playback_snd_device(void * platform,
1600 struct audio_usecase *uc,
1601 struct audio_usecase *new_uc,
1602 snd_device_t new_snd_device)
1603{
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001604 struct listnode a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001605
1606 snd_device_t d1 = uc->out_snd_device;
1607 snd_device_t d2 = new_snd_device;
1608
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001609 list_init(&a1);
1610 list_init(&a2);
1611
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301612 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301613 case TRANSCODE_LOOPBACK_RX :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001614 assign_devices(&a1, &uc->stream.inout->out_config.device_list);
1615 assign_devices(&a2, &new_uc->stream.inout->out_config.device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301616 break;
1617 default :
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001618 assign_devices(&a1, &uc->stream.out->device_list);
1619 assign_devices(&a2, &new_uc->stream.out->device_list);
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301620 break;
1621 }
1622
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001623 // Treat as a special case when a1 and a2 are not disjoint
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001624 if (!compare_devices(&a1, &a2) &&
1625 compare_devices_for_any_match(&a1 ,&a2)) {
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001626 snd_device_t d3[2];
1627 int num_devices = 0;
1628 int ret = platform_split_snd_device(platform,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001629 list_length(&a1) > 1 ? d1 : d2,
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001630 &num_devices,
1631 d3);
1632 if (ret < 0) {
1633 if (ret != -ENOSYS) {
1634 ALOGW("%s failed to split snd_device %d",
1635 __func__,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001636 list_length(&a1) > 1 ? d1 : d2);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001637 }
1638 goto end;
1639 }
1640
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001641 if (platform_check_backends_match(d3[0], d3[1])) {
1642 return d2; // case 5
1643 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001644 if (list_length(&a1) > 1)
Samyak Jaind826b502019-07-17 16:16:42 +05301645 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001646 // check if d1 is related to any of d3's
1647 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001648 return d1; // case 1
1649 else
1650 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001651 }
1652 } else {
1653 if (platform_check_backends_match(d1, d2)) {
1654 return d2; // case 2, 4
1655 } else {
1656 return d1; // case 6, 3
1657 }
1658 }
1659
1660end:
1661 return d2; // return whatever was calculated before.
1662}
1663
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001664static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301665 struct audio_usecase *uc_info,
1666 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001667{
1668 struct listnode *node;
1669 struct audio_usecase *usecase;
1670 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301671 snd_device_t uc_derive_snd_device;
1672 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001673 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1674 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001675 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301676 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001677 /*
1678 * This function is to make sure that all the usecases that are active on
1679 * the hardware codec backend are always routed to any one device that is
1680 * handled by the hardware codec.
1681 * For example, if low-latency and deep-buffer usecases are currently active
1682 * on speaker and out_set_parameters(headset) is received on low-latency
1683 * output, then we have to make sure deep-buffer is also switched to headset,
1684 * because of the limitation that both the devices cannot be enabled
1685 * at the same time as they share the same backend.
1686 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001687 /*
1688 * This call is to check if we need to force routing for a particular stream
1689 * If there is a backend configuration change for the device when a
1690 * new stream starts, then ADM needs to be closed and re-opened with the new
1691 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001692 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001693 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001694 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1695 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301696 /* For a2dp device reconfigure all active sessions
1697 * with new AFE encoder format based on a2dp state
1698 */
1699 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1700 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1701 audio_extn_a2dp_is_force_device_switch()) {
1702 force_routing = true;
1703 force_restart_session = true;
1704 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301705 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1706
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001707 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001708 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001709 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001710 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1711 switch_device[i] = false;
1712
1713 list_for_each(node, &adev->usecase_list) {
1714 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001715
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301716 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1717 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301718 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301719 platform_get_snd_device_name(usecase->out_snd_device),
1720 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301721 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1722 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301723 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1724 usecase, uc_info, snd_device);
1725 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001726 (is_codec_backend_out_device_type(&usecase->device_list) ||
1727 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1728 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_DEVICE) ||
1729 compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_USB_HEADSET) ||
1730 is_a2dp_out_device_type(&usecase->device_list) ||
1731 is_sco_out_device_type(&usecase->device_list)) &&
Ashish Jain6a65b352017-03-21 17:24:40 +05301732 ((force_restart_session) ||
1733 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301734 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1735 __func__, use_case_table[usecase->id],
1736 platform_get_snd_device_name(usecase->out_snd_device));
1737 disable_audio_route(adev, usecase);
1738 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301739 /* Enable existing usecase on derived playback device */
1740 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301741 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301742 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001743 }
1744 }
1745
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301746 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1747 num_uc_to_switch);
1748
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001749 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001750 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001751
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301752 /* Make sure the previous devices to be disabled first and then enable the
1753 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001754 list_for_each(node, &adev->usecase_list) {
1755 usecase = node_to_item(node, struct audio_usecase, list);
1756 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001757 /* Check if output sound device to be switched can be split and if any
1758 of the split devices match with derived sound device */
1759 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1760 &num_devices, split_snd_devices) == 0) {
1761 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1762 for (i = 0; i < num_devices; i++) {
1763 /* Disable devices that do not match with derived sound device */
1764 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1765 disable_snd_device(adev, split_snd_devices[i]);
1766 }
1767 } else {
1768 disable_snd_device(adev, usecase->out_snd_device);
1769 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001770 }
1771 }
1772
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001773 list_for_each(node, &adev->usecase_list) {
1774 usecase = node_to_item(node, struct audio_usecase, list);
1775 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001776 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1777 &num_devices, split_snd_devices) == 0) {
1778 /* Enable derived sound device only if it does not match with
1779 one of the split sound devices. This is because the matching
1780 sound device was not disabled */
1781 bool should_enable = true;
1782 for (i = 0; i < num_devices; i++) {
1783 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1784 should_enable = false;
1785 break;
1786 }
1787 }
1788 if (should_enable)
1789 enable_snd_device(adev, derive_snd_device[usecase->id]);
1790 } else {
1791 enable_snd_device(adev, derive_snd_device[usecase->id]);
1792 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001793 }
1794 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001795
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001796 /* Re-route all the usecases on the shared backend other than the
1797 specified usecase to new snd devices */
1798 list_for_each(node, &adev->usecase_list) {
1799 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301800 /* Update the out_snd_device only before enabling the audio route */
1801 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301802 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301803 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301804 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301805 use_case_table[usecase->id],
1806 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001807 /* Update voc calibration before enabling VoIP route */
1808 if (usecase->type == VOIP_CALL)
1809 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001810 usecase->out_snd_device,
1811 platform_get_input_snd_device(
1812 adev->platform, NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301813 &uc_info->device_list,
1814 usecase->type));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301815 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301816 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001817 out_set_voip_volume(&usecase->stream.out->stream,
1818 usecase->stream.out->volume_l,
1819 usecase->stream.out->volume_r);
1820 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301821 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001822 }
1823 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001824 }
1825}
1826
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301827static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001828 struct audio_usecase *uc_info,
1829 snd_device_t snd_device)
1830{
1831 struct listnode *node;
1832 struct audio_usecase *usecase;
1833 bool switch_device[AUDIO_USECASE_MAX];
1834 int i, num_uc_to_switch = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001835 int backend_check_cond = is_codec_backend_out_device_type(&uc_info->device_list);
kunleiz5cd52b82016-11-07 17:22:52 +08001836 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001837
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301838 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1839 snd_device);
1840 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301841
1842 /*
1843 * Make sure out devices is checked against out codec backend device and
1844 * also in devices against in codec backend. Checking out device against in
1845 * codec backend or vice versa causes issues.
1846 */
1847 if (uc_info->type == PCM_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001848 backend_check_cond = is_codec_backend_in_device_type(&uc_info->device_list);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001849 /*
1850 * This function is to make sure that all the active capture usecases
1851 * are always routed to the same input sound device.
1852 * For example, if audio-record and voice-call usecases are currently
1853 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1854 * is received for voice call then we have to make sure that audio-record
1855 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1856 * because of the limitation that two devices cannot be enabled
1857 * at the same time if they share the same backend.
1858 */
1859 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1860 switch_device[i] = false;
1861
1862 list_for_each(node, &adev->usecase_list) {
1863 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301864 /*
1865 * TODO: Enhance below condition to handle BT sco/USB multi recording
1866 */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301867
1868 bool capture_uc_needs_routing = usecase->type != PCM_PLAYBACK && (usecase != uc_info &&
1869 (usecase->in_snd_device != snd_device || force_routing));
1870 bool call_proxy_snd_device = platform_is_call_proxy_snd_device(snd_device) ||
1871 platform_is_call_proxy_snd_device(usecase->in_snd_device);
1872 if (capture_uc_needs_routing && !call_proxy_snd_device &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001873 ((backend_check_cond &&
1874 (is_codec_backend_in_device_type(&usecase->device_list) ||
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08001875 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001876 ((uc_info->type == VOICE_CALL &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001877 is_single_device_type_equal(&usecase->device_list,
1878 AUDIO_DEVICE_IN_VOICE_CALL)) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001879 platform_check_backends_match(snd_device,\
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08001880 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001881 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05301882 ALOGD("%s: Usecase (%s) is active on (%s) - disabling ..",
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001883 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001884 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001885 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001886 switch_device[usecase->id] = true;
1887 num_uc_to_switch++;
1888 }
1889 }
1890
1891 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001892 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001893
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301894 /* Make sure the previous devices to be disabled first and then enable the
1895 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001896 list_for_each(node, &adev->usecase_list) {
1897 usecase = node_to_item(node, struct audio_usecase, list);
1898 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001899 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001900 }
1901 }
1902
1903 list_for_each(node, &adev->usecase_list) {
1904 usecase = node_to_item(node, struct audio_usecase, list);
1905 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001906 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001907 }
1908 }
1909
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001910 /* Re-route all the usecases on the shared backend other than the
1911 specified usecase to new snd devices */
1912 list_for_each(node, &adev->usecase_list) {
1913 usecase = node_to_item(node, struct audio_usecase, list);
1914 /* Update the in_snd_device only before enabling the audio route */
1915 if (switch_device[usecase->id] ) {
1916 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001917 if (usecase->type != VOICE_CALL) {
1918 /* Update voc calibration before enabling VoIP route */
Jaideep Sharma477917f2020-03-13 18:13:33 +05301919 if (usecase->type == VOIP_CALL) {
1920 snd_device_t voip_snd_device;
1921 voip_snd_device = platform_get_output_snd_device(adev->platform,
1922 uc_info->stream.out,
1923 usecase->type);
kunleiz5cd52b82016-11-07 17:22:52 +08001924 status = platform_switch_voice_call_device_post(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05301925 voip_snd_device,
kunleiz5cd52b82016-11-07 17:22:52 +08001926 usecase->in_snd_device);
Jaideep Sharma477917f2020-03-13 18:13:33 +05301927 }
Avinash Vaish71a8b972014-07-24 15:36:33 +05301928 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001929 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001930 }
1931 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001932 }
1933}
1934
Mingming Yin3a941d42016-02-17 18:08:05 -08001935static void reset_hdmi_sink_caps(struct stream_out *out) {
1936 int i = 0;
1937
1938 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1939 out->supported_channel_masks[i] = 0;
1940 }
1941 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1942 out->supported_formats[i] = 0;
1943 }
1944 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1945 out->supported_sample_rates[i] = 0;
1946 }
1947}
1948
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001949/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001950static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001951{
Mingming Yin3a941d42016-02-17 18:08:05 -08001952 int ret = 0, i = 0, j = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001953 int channels = platform_edid_get_max_channels_v2(out->dev->platform,
1954 out->extconn.cs.controller,
1955 out->extconn.cs.stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001956
Mingming Yin3a941d42016-02-17 18:08:05 -08001957 reset_hdmi_sink_caps(out);
1958
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001959 /* Cache ext disp type */
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001960 if (platform_get_ext_disp_type_v2(adev->platform,
1961 out->extconn.cs.controller,
1962 out->extconn.cs.stream <= 0)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001963 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001964 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001965 }
1966
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001967 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001968 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001969 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001970 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001971 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1972 case 6:
1973 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1974 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1975 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1976 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1977 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1978 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001979 break;
1980 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001981 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001982 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001983 break;
1984 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001985
1986 // check channel format caps
1987 i = 0;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001988 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_AC3,
1989 out->extconn.cs.controller,
1990 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08001991 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1992 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1993 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1994 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1995 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1996 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1997 }
1998
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07001999 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD,
2000 out->extconn.cs.controller,
2001 out->extconn.cs.stream)) {
Ben Romberger1aaaf862017-04-06 17:49:46 -07002002 ALOGV(":%s HDMI supports TRUE HD format", __func__);
2003 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
2004 }
2005
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002006 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS,
2007 out->extconn.cs.controller,
2008 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002009 ALOGV(":%s HDMI supports DTS format", __func__);
2010 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
2011 }
2012
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002013 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_DTS_HD,
2014 out->extconn.cs.controller,
2015 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002016 ALOGV(":%s HDMI supports DTS HD format", __func__);
2017 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
2018 }
2019
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002020 if (platform_is_edid_supported_format_v2(out->dev->platform, AUDIO_FORMAT_IEC61937,
2021 out->extconn.cs.controller,
2022 out->extconn.cs.stream)) {
Naresh Tanniru928f0862017-04-07 16:44:23 -07002023 ALOGV(":%s HDMI supports IEC61937 format", __func__);
2024 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
2025 }
2026
Mingming Yin3a941d42016-02-17 18:08:05 -08002027
2028 // check sample rate caps
2029 i = 0;
2030 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07002031 if (platform_is_edid_supported_sample_rate_v2(out->dev->platform, out_hdmi_sample_rates[j],
2032 out->extconn.cs.controller,
2033 out->extconn.cs.stream)) {
Mingming Yin3a941d42016-02-17 18:08:05 -08002034 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
2035 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
2036 }
2037 }
2038
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07002039 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002040}
2041
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002042static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
2043 uint32_t *supported_sample_rates __unused,
2044 uint32_t max_rates __unused)
2045{
2046 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
2047 supported_sample_rates,
2048 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05302049 ssize_t i = 0;
2050
2051 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002052 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
2053 supported_sample_rates[i]);
2054 }
2055 return count;
2056}
2057
2058static inline int read_usb_sup_channel_masks(bool is_playback,
2059 audio_channel_mask_t *supported_channel_masks,
2060 uint32_t max_masks)
2061{
2062 int channels = audio_extn_usb_get_max_channels(is_playback);
2063 int channel_count;
2064 uint32_t num_masks = 0;
2065 if (channels > MAX_HIFI_CHANNEL_COUNT)
2066 channels = MAX_HIFI_CHANNEL_COUNT;
2067
2068 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07002069 // start from 2 channels as framework currently doesn't support mono.
2070 if (channels >= FCC_2) {
2071 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
2072 }
2073 for (channel_count = FCC_2;
2074 channel_count <= channels && num_masks < max_masks;
2075 ++channel_count) {
2076 supported_channel_masks[num_masks++] =
2077 audio_channel_mask_for_index_assignment_from_count(channel_count);
2078 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002079 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08002080 // For capture we report all supported channel masks from 1 channel up.
2081 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002082 // audio_channel_in_mask_from_count() does the right conversion to either positional or
2083 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07002084 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
2085 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
2086 if (channel_count <= FCC_2) {
2087 mask = audio_channel_in_mask_from_count(channel_count);
2088 supported_channel_masks[num_masks++] = mask;
2089 }
2090 const audio_channel_mask_t index_mask =
2091 audio_channel_mask_for_index_assignment_from_count(channel_count);
2092 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
2093 supported_channel_masks[num_masks++] = index_mask;
2094 }
2095 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002096 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302097
vincenttewf51c94e2019-05-07 10:28:53 +08002098 for (size_t i = 0; i < num_masks; ++i) {
2099 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
2100 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05302101 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07002102 return num_masks;
2103}
2104
2105static inline int read_usb_sup_formats(bool is_playback __unused,
2106 audio_format_t *supported_formats,
2107 uint32_t max_formats __unused)
2108{
2109 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
2110 switch (bitwidth) {
2111 case 24:
2112 // XXX : usb.c returns 24 for s24 and s24_le?
2113 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
2114 break;
2115 case 32:
2116 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
2117 break;
2118 case 16:
2119 default :
2120 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
2121 break;
2122 }
2123 ALOGV("%s: %s supported format %d", __func__,
2124 is_playback ? "P" : "C", bitwidth);
2125 return 1;
2126}
2127
2128static inline int read_usb_sup_params_and_compare(bool is_playback,
2129 audio_format_t *format,
2130 audio_format_t *supported_formats,
2131 uint32_t max_formats,
2132 audio_channel_mask_t *mask,
2133 audio_channel_mask_t *supported_channel_masks,
2134 uint32_t max_masks,
2135 uint32_t *rate,
2136 uint32_t *supported_sample_rates,
2137 uint32_t max_rates) {
2138 int ret = 0;
2139 int num_formats;
2140 int num_masks;
2141 int num_rates;
2142 int i;
2143
2144 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2145 max_formats);
2146 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2147 max_masks);
2148
2149 num_rates = read_usb_sup_sample_rates(is_playback,
2150 supported_sample_rates, max_rates);
2151
2152#define LUT(table, len, what, dflt) \
2153 for (i=0; i<len && (table[i] != what); i++); \
2154 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2155
2156 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2157 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2158 LUT(supported_sample_rates, num_rates, *rate, 0);
2159
2160#undef LUT
2161 return ret < 0 ? -EINVAL : 0; // HACK TBD
2162}
2163
Alexy Josephb1379942016-01-29 15:49:38 -08002164audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002165 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002166{
2167 struct audio_usecase *usecase;
2168 struct listnode *node;
2169
2170 list_for_each(node, &adev->usecase_list) {
2171 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002172 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002173 ALOGV("%s: usecase id %d", __func__, usecase->id);
2174 return usecase->id;
2175 }
2176 }
2177 return USECASE_INVALID;
2178}
2179
Alexy Josephb1379942016-01-29 15:49:38 -08002180struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002181 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002182{
2183 struct audio_usecase *usecase;
2184 struct listnode *node;
2185
2186 list_for_each(node, &adev->usecase_list) {
2187 usecase = node_to_item(node, struct audio_usecase, list);
2188 if (usecase->id == uc_id)
2189 return usecase;
2190 }
2191 return NULL;
2192}
2193
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302194/*
2195 * is a true native playback active
2196 */
2197bool audio_is_true_native_stream_active(struct audio_device *adev)
2198{
2199 bool active = false;
2200 int i = 0;
2201 struct listnode *node;
2202
2203 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2204 ALOGV("%s:napb: not in true mode or non hdphones device",
2205 __func__);
2206 active = false;
2207 goto exit;
2208 }
2209
2210 list_for_each(node, &adev->usecase_list) {
2211 struct audio_usecase *uc;
2212 uc = node_to_item(node, struct audio_usecase, list);
2213 struct stream_out *curr_out =
2214 (struct stream_out*) uc->stream.out;
2215
2216 if (curr_out && PCM_PLAYBACK == uc->type) {
2217 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2218 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2219 uc->id, curr_out->sample_rate,
2220 curr_out->bit_width,
2221 platform_get_snd_device_name(uc->out_snd_device));
2222
2223 if (is_offload_usecase(uc->id) &&
2224 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2225 active = true;
2226 ALOGD("%s:napb:native stream detected", __func__);
2227 }
2228 }
2229 }
2230exit:
2231 return active;
2232}
2233
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002234uint32_t adev_get_dsp_bit_width_enforce_mode()
2235{
2236 if (adev == NULL) {
2237 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2238 return 0;
2239 }
2240 return adev->dsp_bit_width_enforce_mode;
2241}
2242
2243static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2244{
2245 char value[PROPERTY_VALUE_MAX];
2246 int trial;
2247 uint32_t dsp_bit_width_enforce_mode = 0;
2248
2249 if (!mixer) {
2250 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2251 __func__);
2252 return 0;
2253 }
2254
2255 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2256 value, NULL) > 0) {
2257 trial = atoi(value);
2258 switch (trial) {
2259 case 16:
2260 dsp_bit_width_enforce_mode = 16;
2261 break;
2262 case 24:
2263 dsp_bit_width_enforce_mode = 24;
2264 break;
2265 case 32:
2266 dsp_bit_width_enforce_mode = 32;
2267 break;
2268 default:
2269 dsp_bit_width_enforce_mode = 0;
2270 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2271 break;
2272 }
2273 }
2274
2275 return dsp_bit_width_enforce_mode;
2276}
2277
2278static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2279 uint32_t enforce_mode,
2280 bool enable)
2281{
2282 struct mixer_ctl *ctl = NULL;
2283 const char *mixer_ctl_name = "ASM Bit Width";
2284 uint32_t asm_bit_width_mode = 0;
2285
2286 if (enforce_mode == 0) {
2287 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2288 return;
2289 }
2290
2291 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2292 if (!ctl) {
2293 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2294 __func__, mixer_ctl_name);
2295 return;
2296 }
2297
2298 if (enable)
2299 asm_bit_width_mode = enforce_mode;
2300 else
2301 asm_bit_width_mode = 0;
2302
2303 ALOGV("%s DSP bit width feature status is %d width=%d",
2304 __func__, enable, asm_bit_width_mode);
2305 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2306 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2307 asm_bit_width_mode);
2308
2309 return;
2310}
2311
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302312/*
2313 * if native DSD playback active
2314 */
2315bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2316{
2317 bool active = false;
2318 struct listnode *node = NULL;
2319 struct audio_usecase *uc = NULL;
2320 struct stream_out *curr_out = NULL;
2321
2322 list_for_each(node, &adev->usecase_list) {
2323 uc = node_to_item(node, struct audio_usecase, list);
2324 curr_out = (struct stream_out*) uc->stream.out;
2325
2326 if (curr_out && PCM_PLAYBACK == uc->type &&
2327 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2328 active = true;
2329 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302330 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302331 }
2332 }
2333 return active;
2334}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302335
2336static bool force_device_switch(struct audio_usecase *usecase)
2337{
2338 bool ret = false;
2339 bool is_it_true_mode = false;
2340
Zhou Song30f2c3e2018-02-08 14:02:15 +08002341 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302342 usecase->type == TRANSCODE_LOOPBACK_RX ||
2343 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002344 return false;
2345 }
2346
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002347 if(usecase->stream.out == NULL) {
2348 ALOGE("%s: stream.out is NULL", __func__);
2349 return false;
2350 }
2351
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302352 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002353 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002354 (compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADSET) ||
2355 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_WIRED_HEADPHONE))) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302356 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2357 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2358 (!is_it_true_mode && adev->native_playback_enabled)){
2359 ret = true;
2360 ALOGD("napb: time to toggle native mode");
2361 }
2362 }
2363
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302364 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302365 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2366 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002367 if(is_a2dp_out_device_type(&usecase->stream.out->device_list) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302368 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302369 ALOGD("Force a2dp device switch to update new encoder config");
2370 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002371 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302372
Florian Pfister1a84f312018-07-19 14:38:18 +02002373 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302374 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2375 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002376 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302377 return ret;
2378}
2379
Aalique Grahame22e49102018-12-18 14:23:57 -08002380static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2381{
2382 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2383}
2384
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302385bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2386{
2387 bool ret=false;
2388 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
Zhou Song5657f492019-08-07 11:30:39 +08002389 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB ||
2390 out_snd_device == SND_DEVICE_OUT_BT_SCO_SWB) ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302391 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2392 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
Zhou Song5657f492019-08-07 11:30:39 +08002393 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_SWB ||
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302394 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2395 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2396 ret = true;
2397
2398 return ret;
2399}
2400
2401bool is_a2dp_device(snd_device_t out_snd_device)
2402{
2403 bool ret=false;
2404 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2405 ret = true;
2406
2407 return ret;
2408}
2409
2410bool is_bt_soc_on(struct audio_device *adev)
2411{
2412 struct mixer_ctl *ctl;
2413 char *mixer_ctl_name = "BT SOC status";
2414 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2415 bool bt_soc_status = true;
2416 if (!ctl) {
2417 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2418 __func__, mixer_ctl_name);
2419 /*This is to ensure we dont break targets which dont have the kernel change*/
2420 return true;
2421 }
2422 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2423 ALOGD("BT SOC status: %d",bt_soc_status);
2424 return bt_soc_status;
2425}
2426
Zhou Song331c8e52019-08-26 14:16:12 +08002427static int configure_btsco_sample_rate(snd_device_t snd_device)
2428{
2429 struct mixer_ctl *ctl = NULL;
2430 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2431 char *rate_str = NULL;
2432 bool is_rx_dev = true;
2433
2434 if (is_btsco_device(snd_device, snd_device)) {
2435 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2436 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2437 if (!ctl_sr_tx || !ctl_sr_rx) {
2438 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2439 if (!ctl_sr)
2440 return -ENOSYS;
2441 }
2442
2443 switch (snd_device) {
2444 case SND_DEVICE_OUT_BT_SCO:
2445 rate_str = "KHZ_8";
2446 break;
2447 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2448 case SND_DEVICE_IN_BT_SCO_MIC:
2449 rate_str = "KHZ_8";
2450 is_rx_dev = false;
2451 break;
2452 case SND_DEVICE_OUT_BT_SCO_WB:
2453 rate_str = "KHZ_16";
2454 break;
2455 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2456 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2457 rate_str = "KHZ_16";
2458 is_rx_dev = false;
2459 break;
2460 default:
2461 return 0;
2462 }
2463
2464 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2465 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2466 return -ENOSYS;
2467 }
2468 return 0;
2469}
2470
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302471int out_standby_l(struct audio_stream *stream);
2472
Eric Laurent637e2d42018-11-15 12:24:31 -08002473struct stream_in *adev_get_active_input(const struct audio_device *adev)
2474{
2475 struct listnode *node;
2476 struct stream_in *last_active_in = NULL;
2477
2478 /* Get last added active input.
2479 * TODO: We may use a priority mechanism to pick highest priority active source */
2480 list_for_each(node, &adev->usecase_list)
2481 {
2482 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2483 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2484 last_active_in = usecase->stream.in;
2485 }
2486
2487 return last_active_in;
2488}
2489
2490struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2491{
2492 struct listnode *node;
2493
2494 /* First check active inputs with voice communication source and then
2495 * any input if audio mode is in communication */
2496 list_for_each(node, &adev->usecase_list)
2497 {
2498 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2499 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2500 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2501 return usecase->stream.in;
2502 }
2503 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2504 return adev_get_active_input(adev);
2505
2506 return NULL;
2507}
2508
Carter Hsu2e429db2019-05-14 18:50:52 +08002509/*
2510 * Aligned with policy.h
2511 */
2512static inline int source_priority(int inputSource)
2513{
2514 switch (inputSource) {
2515 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2516 return 9;
2517 case AUDIO_SOURCE_CAMCORDER:
2518 return 8;
2519 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2520 return 7;
2521 case AUDIO_SOURCE_UNPROCESSED:
2522 return 6;
2523 case AUDIO_SOURCE_MIC:
2524 return 5;
2525 case AUDIO_SOURCE_ECHO_REFERENCE:
2526 return 4;
2527 case AUDIO_SOURCE_FM_TUNER:
2528 return 3;
2529 case AUDIO_SOURCE_VOICE_RECOGNITION:
2530 return 2;
2531 case AUDIO_SOURCE_HOTWORD:
2532 return 1;
2533 default:
2534 break;
2535 }
2536 return 0;
2537}
2538
2539static struct stream_in *get_priority_input(struct audio_device *adev)
2540{
2541 struct listnode *node;
2542 struct audio_usecase *usecase;
2543 int last_priority = 0, priority;
2544 struct stream_in *priority_in = NULL;
2545 struct stream_in *in;
2546
2547 list_for_each(node, &adev->usecase_list) {
2548 usecase = node_to_item(node, struct audio_usecase, list);
2549 if (usecase->type == PCM_CAPTURE) {
2550 in = usecase->stream.in;
2551 if (!in)
2552 continue;
2553 priority = source_priority(in->source);
2554
2555 if (priority > last_priority) {
2556 last_priority = priority;
2557 priority_in = in;
2558 }
2559 }
2560 }
2561 return priority_in;
2562}
2563
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002564int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002565{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002566 snd_device_t out_snd_device = SND_DEVICE_NONE;
2567 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002568 struct audio_usecase *usecase = NULL;
2569 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002570 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002571 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302572 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002573 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002574 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302576 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2577
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002578 usecase = get_usecase_from_list(adev, uc_id);
2579 if (usecase == NULL) {
2580 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2581 return -EINVAL;
2582 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002583
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002584 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002585 (usecase->type == VOIP_CALL) ||
2586 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302587 if(usecase->stream.out == NULL) {
2588 ALOGE("%s: stream.out is NULL", __func__);
2589 return -EINVAL;
2590 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002591 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS)) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002592 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev,
2593 uc_id);
2594 in_snd_device = audio_extn_auto_hal_get_input_snd_device(adev,
2595 uc_id);
2596 } else {
2597 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302598 usecase->stream.out, usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002599 in_snd_device = platform_get_input_snd_device(adev->platform,
2600 NULL,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302601 &usecase->stream.out->device_list,
2602 usecase->type);
Guodong Hu267bdf82019-08-12 19:22:32 +08002603 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002604 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302605 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302606 if (usecase->stream.inout == NULL) {
2607 ALOGE("%s: stream.inout is NULL", __func__);
2608 return -EINVAL;
2609 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002610 assign_devices(&stream_out.device_list, &usecase->stream.inout->out_config.device_list);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302611 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2612 stream_out.format = usecase->stream.inout->out_config.format;
2613 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
Jaideep Sharma477917f2020-03-13 18:13:33 +05302614 out_snd_device = platform_get_output_snd_device(adev->platform, &stream_out, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002615 assign_devices(&usecase->device_list,
2616 &usecase->stream.inout->out_config.device_list);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302617 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2618 if (usecase->stream.inout == NULL) {
2619 ALOGE("%s: stream.inout is NULL", __func__);
2620 return -EINVAL;
2621 }
Jaideep Sharma477917f2020-03-13 18:13:33 +05302622 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, NULL, usecase->type);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002623 assign_devices(&usecase->device_list,
2624 &usecase->stream.inout->in_config.device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002625 } else {
2626 /*
2627 * If the voice call is active, use the sound devices of voice call usecase
2628 * so that it would not result any device switch. All the usecases will
2629 * be switched to new device when select_devices() is called for voice call
2630 * usecase. This is to avoid switching devices for voice call when
2631 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002632 * choose voice call device only if the use case device is
2633 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002634 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002635 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002636 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002637 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002638 if ((vc_usecase) && ((is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2639 is_codec_backend_out_device_type(&usecase->device_list)) ||
2640 (is_codec_backend_out_device_type(&vc_usecase->device_list) &&
2641 is_codec_backend_in_device_type(&usecase->device_list)) ||
2642 is_single_device_type_equal(&vc_usecase->device_list,
2643 AUDIO_DEVICE_OUT_HEARING_AID) ||
2644 is_single_device_type_equal(&usecase->device_list,
2645 AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002646 in_snd_device = vc_usecase->in_snd_device;
2647 out_snd_device = vc_usecase->out_snd_device;
2648 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002649 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002650 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002651 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002652 if ((voip_usecase != NULL) &&
2653 (usecase->type == PCM_PLAYBACK) &&
2654 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002655 out_snd_device_backend_match = platform_check_backends_match(
2656 voip_usecase->out_snd_device,
2657 platform_get_output_snd_device(
2658 adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302659 usecase->stream.out, usecase->type));
yidongh02ef86f2017-04-21 15:36:04 +08002660 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002661 if ((voip_usecase) && (is_codec_backend_out_device_type(&voip_usecase->device_list) &&
2662 (is_codec_backend_out_device_type(&usecase->device_list) ||
2663 is_codec_backend_in_device_type(&usecase->device_list)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002664 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002665 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002666 in_snd_device = voip_usecase->in_snd_device;
2667 out_snd_device = voip_usecase->out_snd_device;
2668 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002669 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002670 hfp_ucid = audio_extn_hfp_get_usecase();
2671 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002672 if ((hfp_usecase) && is_codec_backend_out_device_type(&hfp_usecase->device_list)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002673 in_snd_device = hfp_usecase->in_snd_device;
2674 out_snd_device = hfp_usecase->out_snd_device;
2675 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002676 }
2677 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302678 if (usecase->stream.out == NULL) {
2679 ALOGE("%s: stream.out is NULL", __func__);
2680 return -EINVAL;
2681 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002682 assign_devices(&usecase->device_list, &usecase->stream.out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002683 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002684 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002685 struct stream_out *voip_out = adev->primary_output;
2686 struct stream_in *voip_in = get_voice_communication_input(adev);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002687 if (compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS))
Guodong Hu267bdf82019-08-12 19:22:32 +08002688 out_snd_device = audio_extn_auto_hal_get_output_snd_device(adev, uc_id);
2689 else
2690 out_snd_device = platform_get_output_snd_device(adev->platform,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302691 usecase->stream.out,
2692 usecase->type);
kunleizdcf967a2018-08-07 17:09:11 +08002693 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002694
Eric Laurent637e2d42018-11-15 12:24:31 -08002695 if (voip_usecase)
2696 voip_out = voip_usecase->stream.out;
2697
2698 if (usecase->stream.out == voip_out && voip_in != NULL)
2699 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002700 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002701 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302702 if (usecase->stream.in == NULL) {
2703 ALOGE("%s: stream.in is NULL", __func__);
2704 return -EINVAL;
2705 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002706 assign_devices(&usecase->device_list, &usecase->stream.in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002707 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002708 if (in_snd_device == SND_DEVICE_NONE) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002709 struct listnode out_devices;
Eric Laurent637e2d42018-11-15 12:24:31 -08002710 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002711 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002712
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002713 list_init(&out_devices);
Eric Laurent637e2d42018-11-15 12:24:31 -08002714 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002715 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2716 USECASE_AUDIO_PLAYBACK_VOIP);
2717
Carter Hsu2e429db2019-05-14 18:50:52 +08002718 usecase->stream.in->enable_ec_port = false;
2719
Eric Laurent637e2d42018-11-15 12:24:31 -08002720 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002721 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_TELEPHONY_TX, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002722 } else if (voip_usecase) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002723 assign_devices(&out_devices, &voip_usecase->stream.out->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002724 } else if (adev->primary_output &&
2725 !adev->primary_output->standby) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002726 assign_devices(&out_devices, &adev->primary_output->device_list);
Eric Laurent637e2d42018-11-15 12:24:31 -08002727 } else {
2728 /* forcing speaker o/p device to get matching i/p pair
2729 in case o/p is not routed from same primary HAL */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002730 reassign_device_list(&out_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Eric Laurent637e2d42018-11-15 12:24:31 -08002731 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002732 priority_in = voip_in;
2733 } else {
2734 /* get the input with the highest priority source*/
2735 priority_in = get_priority_input(adev);
2736
2737 if (!priority_in)
2738 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002739 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002740
Eric Laurent637e2d42018-11-15 12:24:31 -08002741 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002742 priority_in,
Jaideep Sharma477917f2020-03-13 18:13:33 +05302743 &out_devices,
2744 usecase->type);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002745 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002746 }
2747 }
2748
2749 if (out_snd_device == usecase->out_snd_device &&
2750 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302751
2752 if (!force_device_switch(usecase))
2753 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 }
2755
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002756 if (!compare_device_type(&usecase->device_list, AUDIO_DEVICE_OUT_BUS) &&
Guodong Hu267bdf82019-08-12 19:22:32 +08002757 ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002758 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready()))) {
Guodong Hu267bdf82019-08-12 19:22:32 +08002759 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2760 return 0;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302761 }
2762
Aalique Grahame22e49102018-12-18 14:23:57 -08002763 if (out_snd_device != SND_DEVICE_NONE &&
2764 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2765 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2766 __func__,
2767 use_case_table[uc_id],
2768 adev->last_logged_snd_device[uc_id][0],
2769 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2770 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2771 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2772 -1,
2773 out_snd_device,
2774 platform_get_snd_device_name(out_snd_device),
2775 platform_get_snd_device_acdb_id(out_snd_device));
2776 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2777 }
2778 if (in_snd_device != SND_DEVICE_NONE &&
2779 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2780 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2781 __func__,
2782 use_case_table[uc_id],
2783 adev->last_logged_snd_device[uc_id][1],
2784 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2785 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2786 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2787 -1,
2788 in_snd_device,
2789 platform_get_snd_device_name(in_snd_device),
2790 platform_get_snd_device_acdb_id(in_snd_device));
2791 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2792 }
2793
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002794
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795 /*
2796 * Limitation: While in call, to do a device switch we need to disable
2797 * and enable both RX and TX devices though one of them is same as current
2798 * device.
2799 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002800 if ((usecase->type == VOICE_CALL) &&
2801 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2802 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002803 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002804 }
2805
2806 if (((usecase->type == VOICE_CALL) ||
2807 (usecase->type == VOIP_CALL)) &&
2808 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2809 /* Disable sidetone only if voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302810 if (voice_is_call_state_active_in_call(adev) ||
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002811 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002812 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002813
2814 /* Disable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302815 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002816 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002817 }
2818
Aalique Grahame22e49102018-12-18 14:23:57 -08002819 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2820 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002821 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302822 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002823 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2824 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2825 else
2826 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302827 }
2828
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002829 /* Disable current sound devices */
2830 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002831 disable_audio_route(adev, usecase);
2832 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002833 }
2834
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002835 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002836 disable_audio_route(adev, usecase);
2837 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 }
2839
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002840 /* Applicable only on the targets that has external modem.
2841 * New device information should be sent to modem before enabling
2842 * the devices to reduce in-call device switch time.
2843 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002844 if ((usecase->type == VOICE_CALL) &&
2845 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2846 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002847 status = platform_switch_voice_call_enable_device_config(adev->platform,
2848 out_snd_device,
2849 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002850 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002851
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002852 /* Enable new sound devices */
2853 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002854 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302855 if (platform_check_codec_asrc_support(adev->platform))
2856 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002857 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002858 }
2859
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002860 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302861 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002862 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002863 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002864
Avinash Vaish71a8b972014-07-24 15:36:33 +05302865 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002866 status = platform_switch_voice_call_device_post(adev->platform,
2867 out_snd_device,
2868 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302869 enable_audio_route_for_voice_usecases(adev, usecase);
2870 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002871
sangwoo170731f2013-06-08 15:36:36 +09002872 usecase->in_snd_device = in_snd_device;
2873 usecase->out_snd_device = out_snd_device;
2874
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302875 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2876 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302877 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002878 if ((24 == usecase->stream.out->bit_width) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08002879 compare_device_type(&usecase->stream.out->device_list, AUDIO_DEVICE_OUT_SPEAKER)) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002880 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2881 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2882 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2883 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2884 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2885 /*
2886 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2887 * configured device sample rate, if not update the COPP rate to be equal to the
2888 * device sample rate, else open COPP at stream sample rate
2889 */
2890 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2891 usecase->stream.out->sample_rate,
2892 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302893 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawat590d0432019-09-30 14:39:47 +05302894 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2895 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302896 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002897 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2898 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2899 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2900 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002901 }
2902 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002903
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002904 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002905
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002906 /* If input stream is already running then effect needs to be
2907 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002908 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002909 check_and_enable_effect(adev);
2910
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002911 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002912 /* Enable aanc only if voice call exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302913 if (voice_is_call_state_active_in_call(adev))
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002914 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2915
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002916 /* Enable sidetone only if other voice/voip call already exists */
Jaideep Sharma477917f2020-03-13 18:13:33 +05302917 if (voice_is_call_state_active_in_call(adev) ||
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002918 voice_extn_compress_voip_is_started(adev))
2919 voice_set_sidetone(adev, out_snd_device, true);
2920 }
2921
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002922 /* Applicable only on the targets that has external modem.
2923 * Enable device command should be sent to modem only after
2924 * enabling voice call mixer controls
2925 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002926 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002927 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2928 out_snd_device,
2929 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302930
2931 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002932 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302933 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002934 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302935 if (is_bt_soc_on(adev) == false){
2936 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002937 if (in->pcm != NULL)
2938 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302939 }
2940 }
2941 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2942 && usecase->stream.out->started) {
2943 if (is_bt_soc_on(adev) == false) {
2944 ALOGD("BT SCO/A2DP disconnected while in connection");
2945 out_standby_l(&usecase->stream.out->stream.common);
2946 }
2947 }
2948 } else if ((usecase->stream.out != NULL) &&
2949 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302950 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2951 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0d373242019-07-25 13:18:17 +08002952 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302953 usecase->stream.out->started) {
2954 if (is_bt_soc_on(adev) == false) {
2955 ALOGD("BT SCO/A2dp disconnected while in connection");
2956 out_standby_l(&usecase->stream.out->stream.common);
2957 }
2958 }
2959 }
2960
Yung Ti Su70cb8242018-06-22 17:38:47 +08002961 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002962 struct stream_out *voip_out = voip_usecase->stream.out;
2963 audio_extn_utils_send_app_type_gain(adev,
2964 voip_out->app_type_cfg.app_type,
2965 &voip_out->app_type_cfg.gain[0]);
2966 }
2967
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302968 ALOGD("%s: done",__func__);
2969
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002970 return status;
2971}
2972
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002973static int stop_input_stream(struct stream_in *in)
2974{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302975 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002976 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302977
2978 if (in == NULL) {
2979 ALOGE("%s: stream_in ptr is NULL", __func__);
2980 return -EINVAL;
2981 }
2982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002983 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002984 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002985
Eric Laurent994a6932013-07-17 11:51:42 -07002986 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002987 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002988 uc_info = get_usecase_from_list(adev, in->usecase);
2989 if (uc_info == NULL) {
2990 ALOGE("%s: Could not find the usecase (%d) in the list",
2991 __func__, in->usecase);
2992 return -EINVAL;
2993 }
2994
Carter Hsu2e429db2019-05-14 18:50:52 +08002995 priority_in = get_priority_input(adev);
2996
Derek Chenea197282019-01-07 17:35:01 -08002997 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2998 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002999
Vidyakumar Athota2850d532013-11-19 16:02:12 -08003000 /* Close in-call recording streams */
3001 voice_check_and_stop_incall_rec_usecase(adev, in);
3002
Eric Laurent150dbfe2013-02-27 14:31:02 -08003003 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003004 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003005
3006 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003007 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003008
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003009 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303010 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
3011
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003012 list_remove(&uc_info->list);
3013 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003014
Carter Hsu2e429db2019-05-14 18:50:52 +08003015 if (priority_in == in) {
3016 priority_in = get_priority_input(adev);
3017 if (priority_in)
3018 select_devices(adev, priority_in->usecase);
3019 }
3020
Vatsal Buchac09ae062018-11-14 13:25:08 +05303021 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07003022 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003023 return ret;
3024}
3025
3026int start_input_stream(struct stream_in *in)
3027{
3028 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08003029 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003030 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05303031
3032 if (in == NULL) {
3033 ALOGE("%s: stream_in ptr is NULL", __func__);
3034 return -EINVAL;
3035 }
3036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003037 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07003038 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07003039 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003040
Mingming Yin2664a5b2015-09-03 10:53:11 -07003041 if (get_usecase_from_list(adev, usecase) == NULL)
3042 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303043 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
3044 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003045
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303046 if (CARD_STATUS_OFFLINE == in->card_status||
3047 CARD_STATUS_OFFLINE == adev->card_status) {
3048 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303049 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303050 goto error_config;
3051 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303052
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003053 if (is_sco_in_device_type(&in->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303054 if (!adev->bt_sco_on) {
3055 ALOGE("%s: SCO profile is not ready, return error", __func__);
3056 ret = -EIO;
3057 goto error_config;
3058 }
3059 }
3060
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003061 /* Check if source matches incall recording usecase criteria */
3062 ret = voice_check_and_set_incall_rec_usecase(adev, in);
3063 if (ret)
3064 goto error_config;
3065 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07003066 ALOGV("%s: usecase(%d)", __func__, in->usecase);
3067
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303068 if (audio_extn_cin_attached_usecase(in))
3069 audio_extn_cin_acquire_usecase(in);
3070
Mingming Yin2664a5b2015-09-03 10:53:11 -07003071 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3072 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3073 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003074 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003075 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003076
Eric Laurentb23d5282013-05-14 15:27:20 -07003077 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003078 if (in->pcm_device_id < 0) {
3079 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3080 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003081 ret = -EINVAL;
3082 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003083 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003084
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003085 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003086
3087 if (!uc_info) {
3088 ret = -ENOMEM;
3089 goto error_config;
3090 }
3091
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003092 uc_info->id = in->usecase;
3093 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003094 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003095 list_init(&uc_info->device_list);
3096 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003097 uc_info->in_snd_device = SND_DEVICE_NONE;
3098 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003099
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003100 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003101 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303102 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3103 adev->perf_lock_opts,
3104 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003105 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003106
Derek Chenea197282019-01-07 17:35:01 -08003107 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3108 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003109
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303110 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3111
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05303112 if (audio_extn_cin_attached_usecase(in)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303113 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303114 if (ret)
3115 goto error_open;
3116 else
3117 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003118 }
3119
Haynes Mathew George16081042017-05-31 17:16:49 -07003120 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003121 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003122 ALOGE("%s: pcm stream not ready", __func__);
3123 goto error_open;
3124 }
3125 ret = pcm_start(in->pcm);
3126 if (ret < 0) {
3127 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3128 goto error_open;
3129 }
3130 } else {
3131 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3132 unsigned int pcm_open_retry_count = 0;
3133
3134 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
3135 flags |= PCM_MMAP | PCM_NOIRQ;
3136 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3137 } else if (in->realtime) {
3138 flags |= PCM_MMAP | PCM_NOIRQ;
3139 }
3140
Garmond Leunge2433c32017-09-28 21:51:22 -07003141 if (audio_extn_ffv_get_stream() == in) {
3142 ALOGD("%s: ffv stream, update pcm config", __func__);
3143 audio_extn_ffv_update_pcm_config(&config);
3144 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003145 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3146 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3147
3148 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003149 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003150 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003151 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003152 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303153 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303154 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3155 adev->card_status = CARD_STATUS_OFFLINE;
3156 in->card_status = CARD_STATUS_OFFLINE;
3157 ret = -EIO;
3158 goto error_open;
3159 }
3160
Haynes Mathew George16081042017-05-31 17:16:49 -07003161 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3162 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3163 if (in->pcm != NULL) {
3164 pcm_close(in->pcm);
3165 in->pcm = NULL;
3166 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003167 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003168 ret = -EIO;
3169 goto error_open;
3170 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003171 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003172 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3173 continue;
3174 }
3175 break;
3176 }
3177
3178 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003179 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003180 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003181 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003182 if (ret < 0) {
3183 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3184 pcm_close(in->pcm);
3185 in->pcm = NULL;
3186 goto error_open;
3187 }
3188 register_in_stream(in);
3189 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003190 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003191 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003192 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003193 if (ret < 0) {
3194 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003195 pcm_close(in->pcm);
3196 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003197 goto error_open;
3198 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003199 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003200 }
3201
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003202 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003203 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3204 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003205
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003206 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303207 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3208
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303209done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003210 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303211 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003212 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303213 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003214 return ret;
3215
3216error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003217 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303218 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003219 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003220
Eric Laurentc8400632013-02-14 19:04:54 -08003221error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303222 /*
3223 * sleep 50ms to allow sufficient time for kernel
3224 * drivers to recover incases like SSR.
3225 */
3226 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003227 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303228 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003229 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230}
3231
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003232void lock_input_stream(struct stream_in *in)
3233{
3234 pthread_mutex_lock(&in->pre_lock);
3235 pthread_mutex_lock(&in->lock);
3236 pthread_mutex_unlock(&in->pre_lock);
3237}
3238
3239void lock_output_stream(struct stream_out *out)
3240{
3241 pthread_mutex_lock(&out->pre_lock);
3242 pthread_mutex_lock(&out->lock);
3243 pthread_mutex_unlock(&out->pre_lock);
3244}
3245
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003246/* must be called with out->lock locked */
3247static int send_offload_cmd_l(struct stream_out* out, int command)
3248{
3249 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3250
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003251 if (!cmd) {
3252 ALOGE("failed to allocate mem for command 0x%x", command);
3253 return -ENOMEM;
3254 }
3255
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003256 ALOGVV("%s %d", __func__, command);
3257
3258 cmd->cmd = command;
3259 list_add_tail(&out->offload_cmd_list, &cmd->node);
3260 pthread_cond_signal(&out->offload_cond);
3261 return 0;
3262}
3263
3264/* must be called iwth out->lock locked */
3265static void stop_compressed_output_l(struct stream_out *out)
3266{
3267 out->offload_state = OFFLOAD_STATE_IDLE;
3268 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003269 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 if (out->compr != NULL) {
3271 compress_stop(out->compr);
3272 while (out->offload_thread_blocked) {
3273 pthread_cond_wait(&out->cond, &out->lock);
3274 }
3275 }
3276}
3277
Varun Balaraje49253e2017-07-06 19:48:56 +05303278bool is_interactive_usecase(audio_usecase_t uc_id)
3279{
3280 unsigned int i;
3281 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3282 if (uc_id == interactive_usecases[i])
3283 return true;
3284 }
3285 return false;
3286}
3287
3288static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3289{
3290 audio_usecase_t ret_uc = USECASE_INVALID;
3291 unsigned int intract_uc_index;
3292 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3293
3294 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3295 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3296 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3297 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3298 ret_uc = interactive_usecases[intract_uc_index];
3299 break;
3300 }
3301 }
3302
3303 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3304 return ret_uc;
3305}
3306
3307static void free_interactive_usecase(struct audio_device *adev,
3308 audio_usecase_t uc_id)
3309{
3310 unsigned int interact_uc_index;
3311 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3312
3313 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3314 if (interactive_usecases[interact_uc_index] == uc_id) {
3315 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3316 break;
3317 }
3318 }
3319 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3320}
3321
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003322bool is_offload_usecase(audio_usecase_t uc_id)
3323{
3324 unsigned int i;
3325 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3326 if (uc_id == offload_usecases[i])
3327 return true;
3328 }
3329 return false;
3330}
3331
Dhananjay Kumarac341582017-02-23 23:42:25 +05303332static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003333{
vivek mehta446c3962015-09-14 10:57:35 -07003334 audio_usecase_t ret_uc = USECASE_INVALID;
3335 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003336 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003337 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303338 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003339 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3340 else
3341 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003342
vivek mehta446c3962015-09-14 10:57:35 -07003343 pthread_mutex_lock(&adev->lock);
3344 if (get_usecase_from_list(adev, ret_uc) != NULL)
3345 ret_uc = USECASE_INVALID;
3346 pthread_mutex_unlock(&adev->lock);
3347
3348 return ret_uc;
3349 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003350
3351 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003352 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3353 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3354 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3355 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003356 break;
3357 }
3358 }
vivek mehta446c3962015-09-14 10:57:35 -07003359
3360 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3361 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003362}
3363
3364static void free_offload_usecase(struct audio_device *adev,
3365 audio_usecase_t uc_id)
3366{
vivek mehta446c3962015-09-14 10:57:35 -07003367 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003368 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003369
3370 if (!adev->multi_offload_enable)
3371 return;
3372
3373 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3374 if (offload_usecases[offload_uc_index] == uc_id) {
3375 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003376 break;
3377 }
3378 }
3379 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3380}
3381
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003382static void *offload_thread_loop(void *context)
3383{
3384 struct stream_out *out = (struct stream_out *) context;
3385 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003386 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003387
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003388 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003389 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003390 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3391
3392 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003393 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003394 out->offload_state = OFFLOAD_STATE_IDLE;
3395 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003396 for (;;) {
3397 struct offload_cmd *cmd = NULL;
3398 stream_callback_event_t event;
3399 bool send_callback = false;
3400
3401 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3402 __func__, list_empty(&out->offload_cmd_list),
3403 out->offload_state);
3404 if (list_empty(&out->offload_cmd_list)) {
3405 ALOGV("%s SLEEPING", __func__);
3406 pthread_cond_wait(&out->offload_cond, &out->lock);
3407 ALOGV("%s RUNNING", __func__);
3408 continue;
3409 }
3410
3411 item = list_head(&out->offload_cmd_list);
3412 cmd = node_to_item(item, struct offload_cmd, node);
3413 list_remove(item);
3414
3415 ALOGVV("%s STATE %d CMD %d out->compr %p",
3416 __func__, out->offload_state, cmd->cmd, out->compr);
3417
3418 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3419 free(cmd);
3420 break;
3421 }
3422
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003423 // allow OFFLOAD_CMD_ERROR reporting during standby
3424 // this is needed to handle failures during compress_open
3425 // Note however that on a pause timeout, the stream is closed
3426 // and no offload usecase will be active. Therefore this
3427 // special case is needed for compress_open failures alone
3428 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3429 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003430 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003431 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003432 pthread_cond_signal(&out->cond);
3433 continue;
3434 }
3435 out->offload_thread_blocked = true;
3436 pthread_mutex_unlock(&out->lock);
3437 send_callback = false;
3438 switch(cmd->cmd) {
3439 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003440 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003441 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003442 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003443 send_callback = true;
3444 event = STREAM_CBK_EVENT_WRITE_READY;
3445 break;
3446 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003447 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303448 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003449 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303450 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003451 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303452 if (ret < 0)
3453 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303454 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303455 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003456 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003457 else
3458 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003459 if (-ENETRESET != ret && !(-EINTR == ret &&
3460 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303461 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303462 pthread_mutex_lock(&out->lock);
3463 out->send_new_metadata = 1;
3464 out->send_next_track_params = true;
3465 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303466 event = STREAM_CBK_EVENT_DRAIN_READY;
3467 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3468 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303469 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003470 break;
3471 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003472 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003473 ret = compress_drain(out->compr);
3474 ALOGD("copl(%p):out of compress_drain", out);
3475 // EINTR check avoids drain interruption due to SSR
3476 if (-ENETRESET != ret && !(-EINTR == ret &&
3477 CARD_STATUS_OFFLINE == out->card_status)) {
3478 send_callback = true;
3479 event = STREAM_CBK_EVENT_DRAIN_READY;
3480 } else
3481 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003482 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303483 case OFFLOAD_CMD_ERROR:
3484 ALOGD("copl(%p): sending error callback to AF", out);
3485 send_callback = true;
3486 event = STREAM_CBK_EVENT_ERROR;
3487 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003488 default:
3489 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3490 break;
3491 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003492 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003493 out->offload_thread_blocked = false;
3494 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003495 if (send_callback && out->client_callback) {
3496 ALOGVV("%s: sending client_callback event %d", __func__, event);
3497 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003498 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003499 free(cmd);
3500 }
3501
3502 pthread_cond_signal(&out->cond);
3503 while (!list_empty(&out->offload_cmd_list)) {
3504 item = list_head(&out->offload_cmd_list);
3505 list_remove(item);
3506 free(node_to_item(item, struct offload_cmd, node));
3507 }
3508 pthread_mutex_unlock(&out->lock);
3509
3510 return NULL;
3511}
3512
3513static int create_offload_callback_thread(struct stream_out *out)
3514{
3515 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3516 list_init(&out->offload_cmd_list);
3517 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3518 offload_thread_loop, out);
3519 return 0;
3520}
3521
3522static int destroy_offload_callback_thread(struct stream_out *out)
3523{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003524 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003525 stop_compressed_output_l(out);
3526 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3527
3528 pthread_mutex_unlock(&out->lock);
3529 pthread_join(out->offload_thread, (void **) NULL);
3530 pthread_cond_destroy(&out->offload_cond);
3531
3532 return 0;
3533}
3534
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535static int stop_output_stream(struct stream_out *out)
3536{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303537 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538 struct audio_usecase *uc_info;
3539 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003540 bool has_voip_usecase =
3541 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542
Eric Laurent994a6932013-07-17 11:51:42 -07003543 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003544 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003545 uc_info = get_usecase_from_list(adev, out->usecase);
3546 if (uc_info == NULL) {
3547 ALOGE("%s: Could not find the usecase (%d) in the list",
3548 __func__, out->usecase);
3549 return -EINVAL;
3550 }
3551
Derek Chenea197282019-01-07 17:35:01 -08003552 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3553 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003554
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003555 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303556 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003557 if (adev->visualizer_stop_output != NULL)
3558 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003559
3560 audio_extn_dts_remove_state_notifier_node(out->usecase);
3561
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003562 if (adev->offload_effects_stop_output != NULL)
3563 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003564 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3565 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3566 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003567 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003568
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003569 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3570 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003571 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003572 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003573
Eric Laurent150dbfe2013-02-27 14:31:02 -08003574 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003575 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003576
3577 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003578 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003579
Aalique Grahame22e49102018-12-18 14:23:57 -08003580 audio_extn_extspk_update(adev->extspk);
3581
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003582 if (is_offload_usecase(out->usecase)) {
3583 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3584 adev->dsp_bit_width_enforce_mode,
3585 false);
3586 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003587 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003588 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3589 false);
3590
3591 if (ret != 0)
3592 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3593 /* default service interval was successfully updated,
3594 reopen USB backend with new service interval */
3595 ret = 0;
3596 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003597
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003598 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303599 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003600 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303601 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003602 ALOGV("Disable passthrough , reset mixer to pcm");
3603 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003604#ifdef AUDIO_GKI_ENABLED
3605 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3606 out->compr_config.codec->reserved[0] = 0;
3607#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003608 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003609#endif
Mingming Yin21854652016-04-13 11:54:02 -07003610 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003611 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3612 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003613
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303614 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003615 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303616 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303617
Manish Dewangan21a850a2017-08-14 12:03:55 +05303618 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003619 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3620 if (ret < 0)
3621 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3622 }
3623
juyuchen2d415992018-11-16 14:15:16 +08003624 /* 1) media + voip output routing to handset must route media back to
3625 speaker when voip stops.
3626 2) trigger voip input to reroute when voip output changes to
3627 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003628 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003629 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003630 struct listnode *node;
3631 struct audio_usecase *usecase;
3632 list_for_each(node, &adev->usecase_list) {
3633 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003634 if ((usecase->type == PCM_CAPTURE &&
3635 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3636 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003637 continue;
3638
3639 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3640 __func__, usecase->id, use_case_table[usecase->id],
3641 out->usecase, use_case_table[out->usecase]);
3642 select_devices(adev, usecase->id);
3643 }
3644 }
3645
Garmond Leung5fd0b552018-04-17 11:56:12 -07003646 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003647 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003648 return ret;
3649}
3650
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003651struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3652 unsigned int flags, unsigned int pcm_open_retry_count,
3653 struct pcm_config *config)
3654{
3655 struct pcm* pcm = NULL;
3656
3657 while (1) {
3658 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3659 if (pcm == NULL || !pcm_is_ready(pcm)) {
3660 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3661 if (pcm != NULL) {
3662 pcm_close(pcm);
3663 pcm = NULL;
3664 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003665 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003666 return NULL;
3667
Weiyin Jiang72197252019-10-09 11:49:32 +08003668 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003669 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3670 continue;
3671 }
3672 break;
3673 }
3674
3675 if (pcm_is_ready(pcm)) {
3676 int ret = pcm_prepare(pcm);
3677 if (ret < 0) {
3678 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3679 pcm_close(pcm);
3680 pcm = NULL;
3681 }
3682 }
3683
3684 return pcm;
3685}
3686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687int start_output_stream(struct stream_out *out)
3688{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003689 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003690 struct audio_usecase *uc_info;
3691 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003692 char mixer_ctl_name[128];
3693 struct mixer_ctl *ctl = NULL;
3694 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303695 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003696 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003697
Haynes Mathew George380745d2017-10-04 15:27:45 -07003698 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003699 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3700 ret = -EINVAL;
3701 goto error_config;
3702 }
3703
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003704 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303705 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003706 get_device_types(&out->device_list), is_haptic_usecase);
3707
3708 bool is_speaker_active = compare_device_type(&out->device_list,
3709 AUDIO_DEVICE_OUT_SPEAKER);
3710 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3711 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303712
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303713 if (CARD_STATUS_OFFLINE == out->card_status ||
3714 CARD_STATUS_OFFLINE == adev->card_status) {
3715 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303716 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003717 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303718 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303719
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003720 //Update incall music usecase to reflect correct voice session
3721 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3722 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3723 if (ret != 0) {
3724 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3725 __func__, ret);
3726 goto error_config;
3727 }
3728 }
3729
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003730 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003731 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003732 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303733 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303734 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303735 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3736 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3737 ret = -EAGAIN;
3738 goto error_config;
3739 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303740 }
3741 }
3742 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003743 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303744 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003745 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303746 //combo usecase just by pass a2dp
3747 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003748 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303749 } else {
3750 ALOGE("%s: SCO profile is not ready, return error", __func__);
3751 ret = -EAGAIN;
3752 goto error_config;
3753 }
3754 }
3755 }
3756
Eric Laurentb23d5282013-05-14 15:27:20 -07003757 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003758 if (out->pcm_device_id < 0) {
3759 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3760 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003761 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003762 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003763 }
3764
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003765 if (is_haptic_usecase) {
3766 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3767 if (adev->haptic_pcm_device_id < 0) {
3768 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3769 __func__, adev->haptic_pcm_device_id, out->usecase);
3770 ret = -EINVAL;
3771 goto error_config;
3772 }
3773 }
3774
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003775 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003776
3777 if (!uc_info) {
3778 ret = -ENOMEM;
3779 goto error_config;
3780 }
3781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003782 uc_info->id = out->usecase;
3783 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003784 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003785 list_init(&uc_info->device_list);
3786 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003787 uc_info->in_snd_device = SND_DEVICE_NONE;
3788 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003789
3790 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003791 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003792 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3793 /* USB backend is not reopened immediately.
3794 This is eventually done as part of select_devices */
3795 }
3796
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003797 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003798
Wei Wangf7ca6c92017-11-21 14:51:20 -08003799 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303800 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3801 adev->perf_lock_opts,
3802 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303803
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003804 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303805 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303806 if (audio_extn_passthru_is_enabled() &&
3807 audio_extn_passthru_is_passthrough_stream(out)) {
3808 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303809 }
3810 }
3811
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003812 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003813 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303814 if (!a2dp_combo) {
3815 check_a2dp_restore_l(adev, out, false);
3816 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003817 struct listnode dev;
3818 list_init(&dev);
3819 assign_devices(&dev, &out->device_list);
3820 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3821 reassign_device_list(&out->device_list,
3822 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003823 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003824 reassign_device_list(&out->device_list,
3825 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303826 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003827 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303828 }
3829 } else {
3830 select_devices(adev, out->usecase);
3831 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003832
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003833 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3834 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003835 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003836 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003837
Derek Chenea197282019-01-07 17:35:01 -08003838 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3839 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003840
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003841 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3842 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003843
3844 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003845 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003846 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3847 ALOGE("%s: pcm stream not ready", __func__);
3848 goto error_open;
3849 }
3850 ret = pcm_start(out->pcm);
3851 if (ret < 0) {
3852 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3853 goto error_open;
3854 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003855 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003856 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003857 unsigned int flags = PCM_OUT;
3858 unsigned int pcm_open_retry_count = 0;
3859 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3860 flags |= PCM_MMAP | PCM_NOIRQ;
3861 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003862 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003863 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003864 } else
3865 flags |= PCM_MONOTONIC;
3866
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003867 if ((adev->vr_audio_mode_enabled) &&
3868 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3869 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3870 "PCM_Dev %d Topology", out->pcm_device_id);
3871 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3872 if (!ctl) {
3873 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3874 __func__, mixer_ctl_name);
3875 } else {
3876 //if success use ULLPP
3877 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3878 __func__, mixer_ctl_name, out->pcm_device_id);
3879 //There is a still a possibility that some sessions
3880 // that request for FAST|RAW when 3D audio is active
3881 //can go through ULLPP. Ideally we expects apps to
3882 //listen to audio focus and stop concurrent playback
3883 //Also, we will look for mode flag (voice_in_communication)
3884 //before enabling the realtime flag.
3885 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3886 }
3887 }
3888
Surendar Karka91fa3682018-07-02 18:12:12 +05303889 if (out->realtime)
3890 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3891 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3892
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003893 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3894 flags, pcm_open_retry_count,
3895 &(out->config));
3896 if (out->pcm == NULL) {
3897 ret = -EIO;
3898 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003899 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003900
3901 if (is_haptic_usecase) {
3902 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3903 adev->haptic_pcm_device_id,
3904 flags, pcm_open_retry_count,
3905 &(adev->haptics_config));
3906 // failure to open haptics pcm shouldnt stop audio,
3907 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003908
3909 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3910 ALOGD("%s: enable haptic audio synchronization", __func__);
3911 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3912 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003913 }
3914
Surendar Karka91fa3682018-07-02 18:12:12 +05303915 if (!out->realtime)
3916 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303917 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003918
Zhou Song2b8f28f2017-09-11 10:51:38 +08003919 // apply volume for voip playback after path is set up
3920 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3921 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303922 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3923 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303924 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3925 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003926 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3927 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303928 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003929 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003930 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303931 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003932 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3933 adev->dsp_bit_width_enforce_mode,
3934 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003935 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003936 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003937 out->compr = compress_open(adev->snd_card,
3938 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003939 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003940 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303941 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303942 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3943 adev->card_status = CARD_STATUS_OFFLINE;
3944 out->card_status = CARD_STATUS_OFFLINE;
3945 ret = -EIO;
3946 goto error_open;
3947 }
3948
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003949 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003950 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003951 compress_close(out->compr);
3952 out->compr = NULL;
3953 ret = -EIO;
3954 goto error_open;
3955 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303956 /* compress_open sends params of the track, so reset the flag here */
3957 out->is_compr_metadata_avail = false;
3958
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003959 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003960 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003961
Fred Oh3f43e742015-03-04 18:42:34 -08003962 /* Since small bufs uses blocking writes, a write will be blocked
3963 for the default max poll time (20s) in the event of an SSR.
3964 Reduce the poll time to observe and deal with SSR faster.
3965 */
Ashish Jain5106d362016-05-11 19:23:33 +05303966 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003967 compress_set_max_poll_wait(out->compr, 1000);
3968 }
3969
Manish Dewangan69426c82017-01-30 17:35:36 +05303970 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303971 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303972
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003973 audio_extn_dts_create_state_notifier_node(out->usecase);
3974 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3975 popcount(out->channel_mask),
3976 out->playback_started);
3977
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003978#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303979 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003980 audio_extn_dolby_send_ddp_endp_params(adev);
3981#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303982 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3983 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003984 if (adev->visualizer_start_output != NULL)
3985 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3986 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303987 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003988 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003989 }
Derek Chenf13dd492018-11-13 14:53:51 -08003990
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003991 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08003992 /* Update cached volume from media to offload/direct stream */
3993 struct listnode *node = NULL;
3994 list_for_each(node, &adev->active_outputs_list) {
3995 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3996 streams_output_ctxt_t,
3997 list);
3998 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3999 out->volume_l = out_ctxt->output->volume_l;
4000 out->volume_r = out_ctxt->output->volume_r;
4001 }
4002 }
4003 out_set_compr_volume(&out->stream,
4004 out->volume_l, out->volume_r);
4005 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004006 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004007
4008 if (ret == 0) {
4009 register_out_stream(out);
4010 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004011 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4012 ALOGE("%s: pcm stream not ready", __func__);
4013 goto error_open;
4014 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004015 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004016 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004017 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004018 if (ret < 0)
4019 goto error_open;
4020 }
4021 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004022 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304023 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004024 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004025
vivek mehtad15d2bf2019-05-17 13:35:10 -07004026 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4027 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4028 audio_low_latency_hint_start();
4029 }
4030
Manish Dewangan21a850a2017-08-14 12:03:55 +05304031 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004032 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004033 if (ret < 0)
4034 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4035 }
4036
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004037 // consider a scenario where on pause lower layers are tear down.
4038 // so on resume, swap mixer control need to be sent only when
4039 // backend is active, hence rather than sending from enable device
4040 // sending it from start of streamtream
4041
4042 platform_set_swap_channels(adev, true);
4043
Haynes Mathew George380745d2017-10-04 15:27:45 -07004044 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304045 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004046 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004047error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004048 if (adev->haptic_pcm) {
4049 pcm_close(adev->haptic_pcm);
4050 adev->haptic_pcm = NULL;
4051 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004052 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304053 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004054 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004055error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304056 /*
4057 * sleep 50ms to allow sufficient time for kernel
4058 * drivers to recover incases like SSR.
4059 */
4060 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004061error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004062 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304063 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004064 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004065}
4066
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004067static int check_input_parameters(uint32_t sample_rate,
4068 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004069 int channel_count,
4070 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004071{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004072 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004073
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304074 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4075 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4076 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004077 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004078 !audio_extn_compr_cap_format_supported(format) &&
4079 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004080 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004081
Aalique Grahame22e49102018-12-18 14:23:57 -08004082 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4083 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4084 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4085 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4086 return -EINVAL;
4087 }
4088
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004089 switch (channel_count) {
4090 case 1:
4091 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304092 case 3:
4093 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004094 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004095 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304096 case 10:
4097 case 12:
4098 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004099 break;
4100 default:
4101 ret = -EINVAL;
4102 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103
4104 switch (sample_rate) {
4105 case 8000:
4106 case 11025:
4107 case 12000:
4108 case 16000:
4109 case 22050:
4110 case 24000:
4111 case 32000:
4112 case 44100:
4113 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004114 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304115 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004116 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304117 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118 break;
4119 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004120 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121 }
4122
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004123 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004124}
4125
Naresh Tanniru04f71882018-06-26 17:46:22 +05304126
4127/** Add a value in a list if not already present.
4128 * @return true if value was successfully inserted or already present,
4129 * false if the list is full and does not contain the value.
4130 */
4131static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4132 for (size_t i = 0; i < list_length; i++) {
4133 if (list[i] == value) return true; // value is already present
4134 if (list[i] == 0) { // no values in this slot
4135 list[i] = value;
4136 return true; // value inserted
4137 }
4138 }
4139 return false; // could not insert value
4140}
4141
4142/** Add channel_mask in supported_channel_masks if not already present.
4143 * @return true if channel_mask was successfully inserted or already present,
4144 * false if supported_channel_masks is full and does not contain channel_mask.
4145 */
4146static void register_channel_mask(audio_channel_mask_t channel_mask,
4147 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4148 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4149 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4150}
4151
4152/** Add format in supported_formats if not already present.
4153 * @return true if format was successfully inserted or already present,
4154 * false if supported_formats is full and does not contain format.
4155 */
4156static void register_format(audio_format_t format,
4157 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4158 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4159 "%s: stream can not declare supporting its format %x", __func__, format);
4160}
4161/** Add sample_rate in supported_sample_rates if not already present.
4162 * @return true if sample_rate was successfully inserted or already present,
4163 * false if supported_sample_rates is full and does not contain sample_rate.
4164 */
4165static void register_sample_rate(uint32_t sample_rate,
4166 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4167 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4168 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4169}
4170
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004171static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4172{
4173 uint32_t high = num1, low = num2, temp = 0;
4174
4175 if (!num1 || !num2)
4176 return 0;
4177
4178 if (num1 < num2) {
4179 high = num2;
4180 low = num1;
4181 }
4182
4183 while (low != 0) {
4184 temp = low;
4185 low = high % low;
4186 high = temp;
4187 }
4188 return (num1 * num2)/high;
4189}
4190
4191static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4192{
4193 uint32_t remainder = 0;
4194
4195 if (!multiplier)
4196 return num;
4197
4198 remainder = num % multiplier;
4199 if (remainder)
4200 num += (multiplier - remainder);
4201
4202 return num;
4203}
4204
Aalique Grahame22e49102018-12-18 14:23:57 -08004205static size_t get_stream_buffer_size(size_t duration_ms,
4206 uint32_t sample_rate,
4207 audio_format_t format,
4208 int channel_count,
4209 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210{
4211 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004212 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004213
Aalique Grahame22e49102018-12-18 14:23:57 -08004214 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004215 if (is_low_latency)
4216 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304217
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004218 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004219 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220
Ralf Herzbd08d632018-09-28 15:50:49 +02004221 /* make sure the size is multiple of 32 bytes and additionally multiple of
4222 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004223 * At 48 kHz mono 16-bit PCM:
4224 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4225 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004226 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004227 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004228 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004229
4230 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004231}
4232
Aalique Grahame22e49102018-12-18 14:23:57 -08004233static size_t get_input_buffer_size(uint32_t sample_rate,
4234 audio_format_t format,
4235 int channel_count,
4236 bool is_low_latency)
4237{
4238 /* Don't know if USB HIFI in this context so use true to be conservative */
4239 if (check_input_parameters(sample_rate, format, channel_count,
4240 true /*is_usb_hifi */) != 0)
4241 return 0;
4242
4243 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4244 sample_rate,
4245 format,
4246 channel_count,
4247 is_low_latency);
4248}
4249
Derek Chenf6318be2017-06-12 17:16:24 -04004250size_t get_output_period_size(uint32_t sample_rate,
4251 audio_format_t format,
4252 int channel_count,
4253 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304254{
4255 size_t size = 0;
4256 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4257
4258 if ((duration == 0) || (sample_rate == 0) ||
4259 (bytes_per_sample == 0) || (channel_count == 0)) {
4260 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4261 bytes_per_sample, channel_count);
4262 return -EINVAL;
4263 }
4264
4265 size = (sample_rate *
4266 duration *
4267 bytes_per_sample *
4268 channel_count) / 1000;
4269 /*
4270 * To have same PCM samples for all channels, the buffer size requires to
4271 * be multiple of (number of channels * bytes per sample)
4272 * For writes to succeed, the buffer must be written at address which is multiple of 32
4273 */
4274 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4275
4276 return (size/(channel_count * bytes_per_sample));
4277}
4278
Zhou Song48453a02018-01-10 17:50:59 +08004279static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304280{
4281 uint64_t actual_frames_rendered = 0;
4282 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4283
4284 /* This adjustment accounts for buffering after app processor.
4285 * It is based on estimated DSP latency per use case, rather than exact.
4286 */
4287 int64_t platform_latency = platform_render_latency(out->usecase) *
4288 out->sample_rate / 1000000LL;
4289
Zhou Song48453a02018-01-10 17:50:59 +08004290 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304291 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4292 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4293 * hence only estimate.
4294 */
George Gao62ebc722019-07-29 16:29:44 -07004295 uint64_t signed_frames = 0;
4296 if (out->written >= kernel_buffer_size)
4297 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304298
George Gao62ebc722019-07-29 16:29:44 -07004299 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4300 if (signed_frames >= platform_latency)
4301 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304302
Zhou Song48453a02018-01-10 17:50:59 +08004303 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304304 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004305 if (timestamp != NULL )
4306 *timestamp = out->writeAt;
4307 } else if (timestamp != NULL) {
4308 clock_gettime(CLOCK_MONOTONIC, timestamp);
4309 }
4310 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304311
4312 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004313 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304314 (long long int)out->written, (int)kernel_buffer_size,
4315 audio_bytes_per_sample(out->compr_config.codec->format),
4316 popcount(out->channel_mask));
4317
4318 return actual_frames_rendered;
4319}
4320
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004321static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4322{
4323 struct stream_out *out = (struct stream_out *)stream;
4324
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004325 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004326}
4327
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004328static int out_set_sample_rate(struct audio_stream *stream __unused,
4329 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004330{
4331 return -ENOSYS;
4332}
4333
4334static size_t out_get_buffer_size(const struct audio_stream *stream)
4335{
4336 struct stream_out *out = (struct stream_out *)stream;
4337
Varun Balaraje49253e2017-07-06 19:48:56 +05304338 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304339 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304340 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304341 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4342 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4343 else
4344 return out->compr_config.fragment_size;
4345 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004346 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304347 else if (is_offload_usecase(out->usecase) &&
4348 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304349 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004350
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004351 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004352 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004353}
4354
4355static uint32_t out_get_channels(const struct audio_stream *stream)
4356{
4357 struct stream_out *out = (struct stream_out *)stream;
4358
4359 return out->channel_mask;
4360}
4361
4362static audio_format_t out_get_format(const struct audio_stream *stream)
4363{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004364 struct stream_out *out = (struct stream_out *)stream;
4365
4366 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004367}
4368
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004369static int out_set_format(struct audio_stream *stream __unused,
4370 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004371{
4372 return -ENOSYS;
4373}
4374
4375static int out_standby(struct audio_stream *stream)
4376{
4377 struct stream_out *out = (struct stream_out *)stream;
4378 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004379 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004380
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304381 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4382 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004383
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004384 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004385 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004386 if (adev->adm_deregister_stream)
4387 adev->adm_deregister_stream(adev->adm_data, out->handle);
4388
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004389 if (is_offload_usecase(out->usecase))
4390 stop_compressed_output_l(out);
4391
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004392 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004393 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004394 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4395 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304396 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004397 pthread_mutex_unlock(&adev->lock);
4398 pthread_mutex_unlock(&out->lock);
4399 ALOGD("VOIP output entered standby");
4400 return 0;
4401 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004402 if (out->pcm) {
4403 pcm_close(out->pcm);
4404 out->pcm = NULL;
4405 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004406 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4407 do_stop = out->playback_started;
4408 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004409
4410 if (out->mmap_shared_memory_fd >= 0) {
4411 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4412 __func__, out->mmap_shared_memory_fd);
4413 close(out->mmap_shared_memory_fd);
4414 out->mmap_shared_memory_fd = -1;
4415 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004416 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004417 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004418 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304419 out->send_next_track_params = false;
4420 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004421 out->gapless_mdata.encoder_delay = 0;
4422 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004423 if (out->compr != NULL) {
4424 compress_close(out->compr);
4425 out->compr = NULL;
4426 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004427 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004428 if (do_stop) {
4429 stop_output_stream(out);
4430 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304431 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004432 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004433 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434 }
4435 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304436 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004437 return 0;
4438}
4439
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304440static int out_on_error(struct audio_stream *stream)
4441{
4442 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004443 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304444
4445 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004446 // always send CMD_ERROR for offload streams, this
4447 // is needed e.g. when SSR happens within compress_open
4448 // since the stream is active, offload_callback_thread is also active.
4449 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4450 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004451 }
4452 pthread_mutex_unlock(&out->lock);
4453
4454 status = out_standby(&out->stream.common);
4455
4456 lock_output_stream(out);
4457 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004458 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304459 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304460
4461 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4462 ALOGD("Setting previous card status if offline");
4463 out->prev_card_status_offline = true;
4464 }
4465
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304466 pthread_mutex_unlock(&out->lock);
4467
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004468 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304469}
4470
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304471/*
4472 *standby implementation without locks, assumes that the callee already
4473 *has taken adev and out lock.
4474 */
4475int out_standby_l(struct audio_stream *stream)
4476{
4477 struct stream_out *out = (struct stream_out *)stream;
4478 struct audio_device *adev = out->dev;
4479
4480 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4481 stream, out->usecase, use_case_table[out->usecase]);
4482
4483 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004484 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304485 if (adev->adm_deregister_stream)
4486 adev->adm_deregister_stream(adev->adm_data, out->handle);
4487
4488 if (is_offload_usecase(out->usecase))
4489 stop_compressed_output_l(out);
4490
4491 out->standby = true;
4492 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4493 voice_extn_compress_voip_close_output_stream(stream);
4494 out->started = 0;
4495 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004496 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304497 return 0;
4498 } else if (!is_offload_usecase(out->usecase)) {
4499 if (out->pcm) {
4500 pcm_close(out->pcm);
4501 out->pcm = NULL;
4502 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004503 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4504 if (adev->haptic_pcm) {
4505 pcm_close(adev->haptic_pcm);
4506 adev->haptic_pcm = NULL;
4507 }
4508
4509 if (adev->haptic_buffer != NULL) {
4510 free(adev->haptic_buffer);
4511 adev->haptic_buffer = NULL;
4512 adev->haptic_buffer_size = 0;
4513 }
4514 adev->haptic_pcm_device_id = 0;
4515 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304516 } else {
4517 ALOGD("copl(%p):standby", out);
4518 out->send_next_track_params = false;
4519 out->is_compr_metadata_avail = false;
4520 out->gapless_mdata.encoder_delay = 0;
4521 out->gapless_mdata.encoder_padding = 0;
4522 if (out->compr != NULL) {
4523 compress_close(out->compr);
4524 out->compr = NULL;
4525 }
4526 }
4527 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004528 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304529 }
4530 ALOGD("%s: exit", __func__);
4531 return 0;
4532}
4533
Aalique Grahame22e49102018-12-18 14:23:57 -08004534static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535{
Aalique Grahame22e49102018-12-18 14:23:57 -08004536 struct stream_out *out = (struct stream_out *)stream;
4537
4538 // We try to get the lock for consistency,
4539 // but it isn't necessary for these variables.
4540 // If we're not in standby, we may be blocked on a write.
4541 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4542 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4543 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4544
4545 if (locked) {
4546 pthread_mutex_unlock(&out->lock);
4547 }
4548
4549 // dump error info
4550 (void)error_log_dump(
4551 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4552
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004553 return 0;
4554}
4555
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004556static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4557{
4558 int ret = 0;
4559 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004560
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004561 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004562 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004563 return -EINVAL;
4564 }
4565
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304566 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004567
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004568 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4569 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304570 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004571 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004572 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4573 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304574 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004575 }
4576
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004577 ALOGV("%s new encoder delay %u and padding %u", __func__,
4578 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4579
4580 return 0;
4581}
4582
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004583static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4584{
4585 return out == adev->primary_output || out == adev->voice_tx_output;
4586}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004587
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304588// note: this call is safe only if the stream_cb is
4589// removed first in close_output_stream (as is done now).
4590static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4591{
4592 if (!stream || !parms)
4593 return;
4594
4595 struct stream_out *out = (struct stream_out *)stream;
4596 struct audio_device *adev = out->dev;
4597
4598 card_status_t status;
4599 int card;
4600 if (parse_snd_card_status(parms, &card, &status) < 0)
4601 return;
4602
4603 pthread_mutex_lock(&adev->lock);
4604 bool valid_cb = (card == adev->snd_card);
4605 pthread_mutex_unlock(&adev->lock);
4606
4607 if (!valid_cb)
4608 return;
4609
4610 lock_output_stream(out);
4611 if (out->card_status != status)
4612 out->card_status = status;
4613 pthread_mutex_unlock(&out->lock);
4614
4615 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4616 use_case_table[out->usecase],
4617 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4618
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304619 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304620 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304621 if (voice_is_call_state_active(adev) &&
4622 out == adev->primary_output) {
4623 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4624 pthread_mutex_lock(&adev->lock);
4625 voice_stop_call(adev);
4626 adev->mode = AUDIO_MODE_NORMAL;
4627 pthread_mutex_unlock(&adev->lock);
4628 }
4629 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304630 return;
4631}
4632
Kevin Rocardfce19002017-08-07 19:21:36 -07004633static int get_alive_usb_card(struct str_parms* parms) {
4634 int card;
4635 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4636 !audio_extn_usb_alive(card)) {
4637 return card;
4638 }
4639 return -ENODEV;
4640}
4641
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004642int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004643 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004644{
4645 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004646 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004647 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004648 bool bypass_a2dp = false;
4649 bool reconfig = false;
4650 unsigned long service_interval = 0;
4651
4652 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004653 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4654
4655 list_init(&new_devices);
4656 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004657
4658 lock_output_stream(out);
4659 pthread_mutex_lock(&adev->lock);
4660
4661 /*
4662 * When HDMI cable is unplugged the music playback is paused and
4663 * the policy manager sends routing=0. But the audioflinger continues
4664 * to write data until standby time (3sec). As the HDMI core is
4665 * turned off, the write gets blocked.
4666 * Avoid this by routing audio to speaker until standby.
4667 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004668 if (is_single_device_type_equal(&out->device_list,
4669 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004670 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004671 !audio_extn_passthru_is_passthrough_stream(out) &&
4672 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004673 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004674 }
4675 /*
4676 * When A2DP is disconnected the
4677 * music playback is paused and the policy manager sends routing=0
4678 * But the audioflinger continues to write data until standby time
4679 * (3sec). As BT is turned off, the write gets blocked.
4680 * Avoid this by routing audio to speaker until standby.
4681 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004682 if (is_a2dp_out_device_type(&out->device_list) &&
4683 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004684 !audio_extn_a2dp_source_is_ready() &&
4685 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004686 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004687 }
4688 /*
4689 * When USB headset is disconnected the music platback paused
4690 * and the policy manager send routing=0. But if the USB is connected
4691 * back before the standby time, AFE is not closed and opened
4692 * when USB is connected back. So routing to speker will guarantee
4693 * AFE reconfiguration and AFE will be opend once USB is connected again
4694 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004695 if (is_usb_out_device_type(&out->device_list) &&
4696 list_empty(&new_devices) &&
4697 !audio_extn_usb_connected(NULL)) {
4698 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4699 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004700 /* To avoid a2dp to sco overlapping / BT device improper state
4701 * check with BT lib about a2dp streaming support before routing
4702 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004703 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004704 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004705 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4706 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004707 //combo usecase just by pass a2dp
4708 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4709 bypass_a2dp = true;
4710 } else {
4711 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4712 /* update device to a2dp and don't route as BT returned error
4713 * However it is still possible a2dp routing called because
4714 * of current active device disconnection (like wired headset)
4715 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004716 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004717 pthread_mutex_unlock(&adev->lock);
4718 pthread_mutex_unlock(&out->lock);
4719 goto error;
4720 }
4721 }
4722 }
4723
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004724 // Workaround: If routing to an non existing usb device, fail gracefully
4725 // The routing request will otherwise block during 10 second
4726 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004727 if (is_usb_out_device_type(&new_devices)) {
4728 struct str_parms *parms =
4729 str_parms_create_str(get_usb_device_address(&new_devices));
4730 if (!parms)
4731 goto error;
4732 if ((card = get_alive_usb_card(parms)) >= 0) {
4733 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4734 pthread_mutex_unlock(&adev->lock);
4735 pthread_mutex_unlock(&out->lock);
4736 str_parms_destroy(parms);
4737 ret = -ENOSYS;
4738 goto error;
4739 }
4740 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004741 }
4742
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004743 // Workaround: If routing to an non existing hdmi device, fail gracefully
4744 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4745 (platform_get_edid_info_v2(adev->platform,
4746 out->extconn.cs.controller,
4747 out->extconn.cs.stream) != 0)) {
4748 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4749 pthread_mutex_unlock(&adev->lock);
4750 pthread_mutex_unlock(&out->lock);
4751 ret = -ENOSYS;
4752 goto error;
4753 }
4754
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004755 /*
4756 * select_devices() call below switches all the usecases on the same
4757 * backend to the new device. Refer to check_usecases_codec_backend() in
4758 * the select_devices(). But how do we undo this?
4759 *
4760 * For example, music playback is active on headset (deep-buffer usecase)
4761 * and if we go to ringtones and select a ringtone, low-latency usecase
4762 * will be started on headset+speaker. As we can't enable headset+speaker
4763 * and headset devices at the same time, select_devices() switches the music
4764 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4765 * So when the ringtone playback is completed, how do we undo the same?
4766 *
4767 * We are relying on the out_set_parameters() call on deep-buffer output,
4768 * once the ringtone playback is ended.
4769 * NOTE: We should not check if the current devices are same as new devices.
4770 * Because select_devices() must be called to switch back the music
4771 * playback to headset.
4772 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004773 if (!list_empty(&new_devices)) {
4774 bool same_dev = compare_devices(&out->device_list, &new_devices);
4775 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004776
4777 if (output_drives_call(adev, out)) {
4778 if (!voice_is_call_state_active(adev)) {
4779 if (adev->mode == AUDIO_MODE_IN_CALL) {
4780 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004781 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004782 service_interval =
4783 audio_extn_usb_find_service_interval(true, true /*playback*/);
4784 audio_extn_usb_set_service_interval(true /*playback*/,
4785 service_interval,
4786 &reconfig);
4787 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4788 }
4789 ret = voice_start_call(adev);
4790 }
4791 } else {
4792 adev->current_call_output = out;
4793 voice_update_devices_for_all_voice_usecases(adev);
4794 }
4795 }
4796
4797 if (!out->standby) {
4798 if (!same_dev) {
4799 ALOGV("update routing change");
4800 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4801 adev->perf_lock_opts,
4802 adev->perf_lock_opts_size);
4803 if (adev->adm_on_routing_change)
4804 adev->adm_on_routing_change(adev->adm_data,
4805 out->handle);
4806 }
4807 if (!bypass_a2dp) {
4808 select_devices(adev, out->usecase);
4809 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004810 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4811 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004812 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004813 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004814 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004815 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004816 }
4817
4818 if (!same_dev) {
4819 // on device switch force swap, lower functions will make sure
4820 // to check if swap is allowed or not.
4821 platform_set_swap_channels(adev, true);
4822 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4823 }
4824 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4825 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004826 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004827 pthread_mutex_lock(&out->compr_mute_lock);
4828 out->a2dp_compress_mute = false;
4829 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4830 pthread_mutex_unlock(&out->compr_mute_lock);
4831 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4832 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4833 }
4834 }
4835 }
4836
4837 pthread_mutex_unlock(&adev->lock);
4838 pthread_mutex_unlock(&out->lock);
4839
4840 /*handles device and call state changes*/
4841 audio_extn_extspk_update(adev->extspk);
4842
4843error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004844 ALOGV("%s: exit: code(%d)", __func__, ret);
4845 return ret;
4846}
4847
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004848static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4849{
4850 struct stream_out *out = (struct stream_out *)stream;
4851 struct audio_device *adev = out->dev;
4852 struct str_parms *parms;
4853 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004854 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004855 int ext_controller = -1;
4856 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857
sangwoobc677242013-08-08 16:53:43 +09004858 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004859 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004860 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304861 if (!parms)
4862 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004863
4864 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4865 &ext_stream);
4866 if (err >= 0) {
4867 out->extconn.cs.controller = ext_controller;
4868 out->extconn.cs.stream = ext_stream;
4869 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4870 use_case_table[out->usecase], out->extconn.cs.controller,
4871 out->extconn.cs.stream);
4872 }
4873
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004874 if (out == adev->primary_output) {
4875 pthread_mutex_lock(&adev->lock);
4876 audio_extn_set_parameters(adev, parms);
4877 pthread_mutex_unlock(&adev->lock);
4878 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004879 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004880 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004881 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004882
4883 audio_extn_dts_create_state_notifier_node(out->usecase);
4884 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4885 popcount(out->channel_mask),
4886 out->playback_started);
4887
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004888 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004889 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004890
Surendar Karkaf51b5842018-04-26 11:28:38 +05304891 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4892 sizeof(value));
4893 if (err >= 0) {
4894 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4895 audio_extn_send_dual_mono_mixing_coefficients(out);
4896 }
4897
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304898 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4899 if (err >= 0) {
4900 strlcpy(out->profile, value, sizeof(out->profile));
4901 ALOGV("updating stream profile with value '%s'", out->profile);
4902 lock_output_stream(out);
4903 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4904 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004905 &out->device_list, out->flags,
4906 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304907 out->sample_rate, out->bit_width,
4908 out->channel_mask, out->profile,
4909 &out->app_type_cfg);
4910 pthread_mutex_unlock(&out->lock);
4911 }
4912
Alexy Joseph98988832017-01-13 14:56:59 -08004913 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004914 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4915 // and vendor.audio.hal.output.suspend.supported is set to true
4916 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004917 //check suspend parameter only for low latency and if the property
4918 //is enabled
4919 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4920 ALOGI("%s: got suspend_playback %s", __func__, value);
4921 lock_output_stream(out);
4922 if (!strncmp(value, "false", 5)) {
4923 //suspend_playback=false is supposed to set QOS value back to 75%
4924 //the mixer control sent with value Enable will achieve that
4925 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4926 } else if (!strncmp (value, "true", 4)) {
4927 //suspend_playback=true is supposed to remove QOS value
4928 //resetting the mixer control will set the default value
4929 //for the mixer control which is Disable and this removes the QOS vote
4930 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4931 } else {
4932 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4933 " got %s", __func__, value);
4934 ret = -1;
4935 }
4936
4937 if (ret != 0) {
4938 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4939 __func__, out->pm_qos_mixer_path, ret);
4940 }
4941
4942 pthread_mutex_unlock(&out->lock);
4943 }
4944 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004945
Alexy Joseph98988832017-01-13 14:56:59 -08004946 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004947 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304948error:
Eric Laurent994a6932013-07-17 11:51:42 -07004949 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004950 return ret;
4951}
4952
Paul McLeana50b7332018-12-17 08:24:21 -07004953static int in_set_microphone_direction(const struct audio_stream_in *stream,
4954 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004955 struct stream_in *in = (struct stream_in *)stream;
4956
4957 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4958
4959 in->direction = dir;
4960
4961 if (in->standby)
4962 return 0;
4963
4964 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004965}
4966
4967static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004968 struct stream_in *in = (struct stream_in *)stream;
4969
4970 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4971
4972 if (zoom > 1.0 || zoom < -1.0)
4973 return -EINVAL;
4974
4975 in->zoom = zoom;
4976
4977 if (in->standby)
4978 return 0;
4979
4980 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004981}
4982
4983
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004984static bool stream_get_parameter_channels(struct str_parms *query,
4985 struct str_parms *reply,
4986 audio_channel_mask_t *supported_channel_masks) {
4987 int ret = -1;
4988 char value[512];
4989 bool first = true;
4990 size_t i, j;
4991
4992 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4993 ret = 0;
4994 value[0] = '\0';
4995 i = 0;
4996 while (supported_channel_masks[i] != 0) {
4997 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4998 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4999 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305000 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005001
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305002 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005003 first = false;
5004 break;
5005 }
5006 }
5007 i++;
5008 }
5009 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5010 }
5011 return ret == 0;
5012}
5013
5014static bool stream_get_parameter_formats(struct str_parms *query,
5015 struct str_parms *reply,
5016 audio_format_t *supported_formats) {
5017 int ret = -1;
5018 char value[256];
5019 size_t i, j;
5020 bool first = true;
5021
5022 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5023 ret = 0;
5024 value[0] = '\0';
5025 i = 0;
5026 while (supported_formats[i] != 0) {
5027 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5028 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5029 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305030 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005031 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305032 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005033 first = false;
5034 break;
5035 }
5036 }
5037 i++;
5038 }
5039 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5040 }
5041 return ret == 0;
5042}
5043
5044static bool stream_get_parameter_rates(struct str_parms *query,
5045 struct str_parms *reply,
5046 uint32_t *supported_sample_rates) {
5047
5048 int i;
5049 char value[256];
5050 int ret = -1;
5051 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5052 ret = 0;
5053 value[0] = '\0';
5054 i=0;
5055 int cursor = 0;
5056 while (supported_sample_rates[i]) {
5057 int avail = sizeof(value) - cursor;
5058 ret = snprintf(value + cursor, avail, "%s%d",
5059 cursor > 0 ? "|" : "",
5060 supported_sample_rates[i]);
5061 if (ret < 0 || ret >= avail) {
5062 // if cursor is at the last element of the array
5063 // overwrite with \0 is duplicate work as
5064 // snprintf already put a \0 in place.
5065 // else
5066 // we had space to write the '|' at value[cursor]
5067 // (which will be overwritten) or no space to fill
5068 // the first element (=> cursor == 0)
5069 value[cursor] = '\0';
5070 break;
5071 }
5072 cursor += ret;
5073 ++i;
5074 }
5075 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5076 value);
5077 }
5078 return ret >= 0;
5079}
5080
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005081static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5082{
5083 struct stream_out *out = (struct stream_out *)stream;
5084 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005085 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005086 char value[256];
5087 struct str_parms *reply = str_parms_create();
5088 size_t i, j;
5089 int ret;
5090 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005091
5092 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005093 if (reply) {
5094 str_parms_destroy(reply);
5095 }
5096 if (query) {
5097 str_parms_destroy(query);
5098 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005099 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5100 return NULL;
5101 }
5102
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005103 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005104 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5105 if (ret >= 0) {
5106 value[0] = '\0';
5107 i = 0;
5108 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005109 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5110 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005111 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005112 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005113 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005114 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 first = false;
5116 break;
5117 }
5118 }
5119 i++;
5120 }
5121 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5122 str = str_parms_to_str(reply);
5123 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005124 voice_extn_out_get_parameters(out, query, reply);
5125 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005126 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005127
Alexy Joseph62142aa2015-11-16 15:10:34 -08005128
5129 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5130 if (ret >= 0) {
5131 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305132 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5133 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005134 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305135 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005136 } else {
5137 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305138 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005139 }
5140 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005141 if (str)
5142 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005143 str = str_parms_to_str(reply);
5144 }
5145
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005146 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5147 if (ret >= 0) {
5148 value[0] = '\0';
5149 i = 0;
5150 first = true;
5151 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005152 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5153 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005154 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005155 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005156 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005157 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005158 first = false;
5159 break;
5160 }
5161 }
5162 i++;
5163 }
5164 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005165 if (str)
5166 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005167 str = str_parms_to_str(reply);
5168 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005169
5170 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5171 if (ret >= 0) {
5172 value[0] = '\0';
5173 i = 0;
5174 first = true;
5175 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005176 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5177 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005178 if (!first) {
5179 strlcat(value, "|", sizeof(value));
5180 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005181 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005182 first = false;
5183 break;
5184 }
5185 }
5186 i++;
5187 }
5188 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5189 if (str)
5190 free(str);
5191 str = str_parms_to_str(reply);
5192 }
5193
Alexy Joseph98988832017-01-13 14:56:59 -08005194 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5195 //only low latency track supports suspend_resume
5196 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005197 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005198 if (str)
5199 free(str);
5200 str = str_parms_to_str(reply);
5201 }
5202
5203
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005204 str_parms_destroy(query);
5205 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005206 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005207 return str;
5208}
5209
5210static uint32_t out_get_latency(const struct audio_stream_out *stream)
5211{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005212 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005213 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005214 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005215
Alexy Josephaa54c872014-12-03 02:46:47 -08005216 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305217 lock_output_stream(out);
5218 latency = audio_extn_utils_compress_get_dsp_latency(out);
5219 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005220 } else if ((out->realtime) ||
5221 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005222 // since the buffer won't be filled up faster than realtime,
5223 // return a smaller number
5224 if (out->config.rate)
5225 period_ms = (out->af_period_multiplier * out->config.period_size *
5226 1000) / (out->config.rate);
5227 else
5228 period_ms = 0;
5229 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005230 } else {
5231 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005232 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005233 }
5234
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005235 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005236 latency += audio_extn_a2dp_get_encoder_latency();
5237
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305238 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005239 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240}
5241
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305242static float AmpToDb(float amplification)
5243{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305244 float db = DSD_VOLUME_MIN_DB;
5245 if (amplification > 0) {
5246 db = 20 * log10(amplification);
5247 if(db < DSD_VOLUME_MIN_DB)
5248 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305249 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305250 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305251}
5252
Arun Mirpuri5d170872019-03-26 13:21:31 -07005253static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5254 float right)
5255{
5256 struct stream_out *out = (struct stream_out *)stream;
5257 long volume = 0;
5258 char mixer_ctl_name[128] = "";
5259 struct audio_device *adev = out->dev;
5260 struct mixer_ctl *ctl = NULL;
5261 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5262 PCM_PLAYBACK);
5263
5264 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5265 "Playback %d Volume", pcm_device_id);
5266 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5267 if (!ctl) {
5268 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5269 __func__, mixer_ctl_name);
5270 return -EINVAL;
5271 }
5272 if (left != right)
5273 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5274 __func__, left, right);
5275 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5276 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5277 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5278 __func__, mixer_ctl_name, volume);
5279 return -EINVAL;
5280 }
5281 return 0;
5282}
5283
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305284static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5285 float right)
5286{
5287 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305288 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305289 char mixer_ctl_name[128];
5290 struct audio_device *adev = out->dev;
5291 struct mixer_ctl *ctl;
5292 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5293 PCM_PLAYBACK);
5294
5295 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5296 "Compress Playback %d Volume", pcm_device_id);
5297 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5298 if (!ctl) {
5299 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5300 __func__, mixer_ctl_name);
5301 return -EINVAL;
5302 }
5303 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5304 __func__, mixer_ctl_name, left, right);
5305 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5306 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5307 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5308
5309 return 0;
5310}
5311
Zhou Song2b8f28f2017-09-11 10:51:38 +08005312static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5313 float right)
5314{
5315 struct stream_out *out = (struct stream_out *)stream;
5316 char mixer_ctl_name[] = "App Type Gain";
5317 struct audio_device *adev = out->dev;
5318 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305319 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005320
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005321 if (!is_valid_volume(left, right)) {
5322 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5323 __func__, left, right);
5324 return -EINVAL;
5325 }
5326
Zhou Song2b8f28f2017-09-11 10:51:38 +08005327 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5328 if (!ctl) {
5329 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5330 __func__, mixer_ctl_name);
5331 return -EINVAL;
5332 }
5333
5334 set_values[0] = 0; //0: Rx Session 1:Tx Session
5335 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305336 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5337 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005338
5339 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5340 return 0;
5341}
5342
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305343static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5344 float right)
5345{
5346 struct stream_out *out = (struct stream_out *)stream;
5347 /* Volume control for pcm playback */
5348 if (left != right) {
5349 return -EINVAL;
5350 } else {
5351 char mixer_ctl_name[128];
5352 struct audio_device *adev = out->dev;
5353 struct mixer_ctl *ctl;
5354 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5355 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5356 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5357 if (!ctl) {
5358 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5359 return -EINVAL;
5360 }
5361
5362 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5363 int ret = mixer_ctl_set_value(ctl, 0, volume);
5364 if (ret < 0) {
5365 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5366 return -EINVAL;
5367 }
5368
5369 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5370
5371 return 0;
5372 }
5373}
5374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005375static int out_set_volume(struct audio_stream_out *stream, float left,
5376 float right)
5377{
Eric Laurenta9024de2013-04-04 09:19:12 -07005378 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005379 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305380 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005381
Arun Mirpuri5d170872019-03-26 13:21:31 -07005382 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005383 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5384 /* only take left channel into account: the API is for stereo anyway */
5385 out->muted = (left == 0.0f);
5386 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005387 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305388 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005389 /*
5390 * Set mute or umute on HDMI passthrough stream.
5391 * Only take left channel into account.
5392 * Mute is 0 and unmute 1
5393 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305394 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305395 } else if (out->format == AUDIO_FORMAT_DSD){
5396 char mixer_ctl_name[128] = "DSD Volume";
5397 struct audio_device *adev = out->dev;
5398 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5399
5400 if (!ctl) {
5401 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5402 __func__, mixer_ctl_name);
5403 return -EINVAL;
5404 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305405 volume[0] = (long)(AmpToDb(left));
5406 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305407 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5408 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005409 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005410 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005411 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5412 struct listnode *node = NULL;
5413 list_for_each(node, &adev->active_outputs_list) {
5414 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5415 streams_output_ctxt_t,
5416 list);
5417 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5418 out->volume_l = out_ctxt->output->volume_l;
5419 out->volume_r = out_ctxt->output->volume_r;
5420 }
5421 }
5422 if (!out->a2dp_compress_mute) {
5423 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5424 }
5425 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005426 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305427 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005428 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305429 if (!out->a2dp_compress_mute)
5430 ret = out_set_compr_volume(stream, left, right);
5431 out->volume_l = left;
5432 out->volume_r = right;
5433 pthread_mutex_unlock(&out->compr_mute_lock);
5434 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005435 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005436 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005437 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5438 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5439 if (!out->standby) {
5440 audio_extn_utils_send_app_type_gain(out->dev,
5441 out->app_type_cfg.app_type,
5442 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005443 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005444 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005445 out->volume_l = left;
5446 out->volume_r = right;
5447 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005448 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5449 ALOGV("%s: MMAP set volume called", __func__);
5450 if (!out->standby)
5451 ret = out_set_mmap_volume(stream, left, right);
5452 out->volume_l = left;
5453 out->volume_r = right;
5454 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305455 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305456 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5457 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305458 /* Volume control for pcm playback */
5459 if (!out->standby)
5460 ret = out_set_pcm_volume(stream, left, right);
5461 else
5462 out->apply_volume = true;
5463
5464 out->volume_l = left;
5465 out->volume_r = right;
5466 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005467 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5468 ALOGV("%s: bus device set volume called", __func__);
5469 if (!out->standby)
5470 ret = out_set_pcm_volume(stream, left, right);
5471 out->volume_l = left;
5472 out->volume_r = right;
5473 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005474 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005475
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476 return -ENOSYS;
5477}
5478
Zhou Songc9672822017-08-16 16:01:39 +08005479static void update_frames_written(struct stream_out *out, size_t bytes)
5480{
5481 size_t bpf = 0;
5482
5483 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5484 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5485 bpf = 1;
5486 else if (!is_offload_usecase(out->usecase))
5487 bpf = audio_bytes_per_sample(out->format) *
5488 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005489
5490 pthread_mutex_lock(&out->position_query_lock);
5491 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005492 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005493 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5494 }
5495 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005496}
5497
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005498int split_and_write_audio_haptic_data(struct stream_out *out,
5499 const void *buffer, size_t bytes_to_write)
5500{
5501 struct audio_device *adev = out->dev;
5502
5503 int ret = 0;
5504 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5505 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5506 size_t frame_size = channel_count * bytes_per_sample;
5507 size_t frame_count = bytes_to_write / frame_size;
5508
5509 bool force_haptic_path =
5510 property_get_bool("vendor.audio.test_haptic", false);
5511
5512 // extract Haptics data from Audio buffer
5513 bool alloc_haptic_buffer = false;
5514 int haptic_channel_count = adev->haptics_config.channels;
5515 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5516 size_t audio_frame_size = frame_size - haptic_frame_size;
5517 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5518
5519 if (adev->haptic_buffer == NULL) {
5520 alloc_haptic_buffer = true;
5521 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5522 free(adev->haptic_buffer);
5523 adev->haptic_buffer_size = 0;
5524 alloc_haptic_buffer = true;
5525 }
5526
5527 if (alloc_haptic_buffer) {
5528 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005529 if(adev->haptic_buffer == NULL) {
5530 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5531 return -ENOMEM;
5532 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005533 adev->haptic_buffer_size = total_haptic_buffer_size;
5534 }
5535
5536 size_t src_index = 0, aud_index = 0, hap_index = 0;
5537 uint8_t *audio_buffer = (uint8_t *)buffer;
5538 uint8_t *haptic_buffer = adev->haptic_buffer;
5539
5540 // This is required for testing only. This works for stereo data only.
5541 // One channel is fed to audio stream and other to haptic stream for testing.
5542 if (force_haptic_path)
5543 audio_frame_size = haptic_frame_size = bytes_per_sample;
5544
5545 for (size_t i = 0; i < frame_count; i++) {
5546 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5547 audio_frame_size);
5548 aud_index += audio_frame_size;
5549 src_index += audio_frame_size;
5550
5551 if (adev->haptic_pcm)
5552 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5553 haptic_frame_size);
5554 hap_index += haptic_frame_size;
5555 src_index += haptic_frame_size;
5556
5557 // This is required for testing only.
5558 // Discard haptic channel data.
5559 if (force_haptic_path)
5560 src_index += haptic_frame_size;
5561 }
5562
5563 // write to audio pipeline
5564 ret = pcm_write(out->pcm, (void *)audio_buffer,
5565 frame_count * audio_frame_size);
5566
5567 // write to haptics pipeline
5568 if (adev->haptic_pcm)
5569 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5570 frame_count * haptic_frame_size);
5571
5572 return ret;
5573}
5574
Aalique Grahame22e49102018-12-18 14:23:57 -08005575#ifdef NO_AUDIO_OUT
5576static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5577 const void *buffer __unused, size_t bytes)
5578{
5579 struct stream_out *out = (struct stream_out *)stream;
5580
5581 /* No Output device supported other than BT for playback.
5582 * Sleep for the amount of buffer duration
5583 */
5584 lock_output_stream(out);
5585 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5586 (const struct audio_stream_out *)&out->stream) /
5587 out_get_sample_rate(&out->stream.common));
5588 pthread_mutex_unlock(&out->lock);
5589 return bytes;
5590}
5591#endif
5592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005593static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5594 size_t bytes)
5595{
5596 struct stream_out *out = (struct stream_out *)stream;
5597 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005598 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305599 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005600 const size_t frame_size = audio_stream_out_frame_size(stream);
5601 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305602 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005603 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005604
Haynes Mathew George380745d2017-10-04 15:27:45 -07005605 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005606 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305607
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305608 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005609
Dhananjay Kumarac341582017-02-23 23:42:25 +05305610 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305611 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305612 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5613 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005614 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305615 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305616 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305617 ALOGD(" %s: sound card is not active/SSR state", __func__);
5618 ret= -EIO;
5619 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305620 }
5621 }
5622
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305623 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305624 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305625 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305626 goto exit;
5627 }
5628
Haynes Mathew George16081042017-05-31 17:16:49 -07005629 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5630 ret = -EINVAL;
5631 goto exit;
5632 }
5633
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005634 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305635 !out->is_iec61937_info_available) {
5636
5637 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5638 out->is_iec61937_info_available = true;
5639 } else if (audio_extn_passthru_is_enabled()) {
5640 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305641 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305642
5643 if((out->format == AUDIO_FORMAT_DTS) ||
5644 (out->format == AUDIO_FORMAT_DTS_HD)) {
5645 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5646 buffer, bytes);
5647 if (ret) {
5648 if (ret != -ENOSYS) {
5649 out->is_iec61937_info_available = false;
5650 ALOGD("iec61937 transmission info not yet updated retry");
5651 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305652 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305653 /* if stream has started and after that there is
5654 * stream config change (iec transmission config)
5655 * then trigger select_device to update backend configuration.
5656 */
5657 out->stream_config_changed = true;
5658 pthread_mutex_lock(&adev->lock);
5659 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305660 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005661 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305662 ret = -EINVAL;
5663 goto exit;
5664 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305665 pthread_mutex_unlock(&adev->lock);
5666 out->stream_config_changed = false;
5667 out->is_iec61937_info_available = true;
5668 }
5669 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305670
Meng Wang4c32fb42020-01-16 17:57:11 +08005671#ifdef AUDIO_GKI_ENABLED
5672 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5673 compr_passthr = out->compr_config.codec->reserved[0];
5674#else
5675 compr_passthr = out->compr_config.codec->compr_passthr;
5676#endif
5677
Garmond Leung317cbf12017-09-13 16:20:50 -07005678 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005679 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305680 (out->is_iec61937_info_available == true)) {
5681 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5682 ret = -EINVAL;
5683 goto exit;
5684 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305685 }
5686 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305687
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005688 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005689 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005690 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5691 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305692 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305693 ret = -EIO;
5694 goto exit;
5695 }
5696 }
5697 }
5698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005699 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005700 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005701 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005702 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5703 ret = voice_extn_compress_voip_start_output_stream(out);
5704 else
5705 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005706 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005707 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005708 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005709 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005710 goto exit;
5711 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305712 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005713 if (last_known_cal_step != -1) {
5714 ALOGD("%s: retry previous failed cal level set", __func__);
5715 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305716 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005717 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305718
5719 if ((out->is_iec61937_info_available == true) &&
5720 (audio_extn_passthru_is_passthrough_stream(out))&&
5721 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5722 ret = -EINVAL;
5723 goto exit;
5724 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305725 if (out->set_dual_mono)
5726 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005728
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005729 if (adev->is_channel_status_set == false &&
5730 compare_device_type(&out->device_list,
5731 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005732 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305733 adev->is_channel_status_set = true;
5734 }
5735
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305736 if ((adev->use_old_pspd_mix_ctrl == true) &&
5737 (out->pspd_coeff_sent == false)) {
5738 /*
5739 * Need to resend pspd coefficients after stream started for
5740 * older kernel version as it does not save the coefficients
5741 * and also stream has to be started for coeff to apply.
5742 */
5743 usecase = get_usecase_from_list(adev, out->usecase);
5744 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305745 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305746 out->pspd_coeff_sent = true;
5747 }
5748 }
5749
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005750 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005751 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005752 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005753 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005754 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5755 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305756 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5757 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005758 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305759 out->send_next_track_params = false;
5760 out->is_compr_metadata_avail = false;
5761 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005762 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305763 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305764 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005765
Ashish Jain83a6cc22016-06-28 14:34:17 +05305766 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305767 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305768 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305769 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005770 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305771 return -EINVAL;
5772 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305773 audio_format_t dst_format = out->hal_op_format;
5774 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305775
Dieter Luecking5d57def2018-09-07 14:23:37 +02005776 /* prevent division-by-zero */
5777 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5778 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5779 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5780 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305781 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005782 ATRACE_END();
5783 return -EINVAL;
5784 }
5785
Ashish Jainf1eaa582016-05-23 20:54:24 +05305786 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5787 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5788
Ashish Jain83a6cc22016-06-28 14:34:17 +05305789 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305790 dst_format,
5791 buffer,
5792 src_format,
5793 frames);
5794
Ashish Jain83a6cc22016-06-28 14:34:17 +05305795 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305796 bytes_to_write);
5797
5798 /*Convert written bytes in audio flinger format*/
5799 if (ret > 0)
5800 ret = ((ret * format_to_bitwidth_table[out->format]) /
5801 format_to_bitwidth_table[dst_format]);
5802 }
5803 } else
5804 ret = compress_write(out->compr, buffer, bytes);
5805
Zhou Songc9672822017-08-16 16:01:39 +08005806 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5807 update_frames_written(out, bytes);
5808
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305809 if (ret < 0)
5810 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005811 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305812 /*msg to cb thread only if non blocking write is enabled*/
5813 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305814 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005815 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305816 } else if (-ENETRESET == ret) {
5817 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305818 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305819 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305820 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005821 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305822 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005823 }
Ashish Jain5106d362016-05-11 19:23:33 +05305824
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305825 /* Call compr start only when non-zero bytes of data is there to be rendered */
5826 if (!out->playback_started && ret > 0) {
5827 int status = compress_start(out->compr);
5828 if (status < 0) {
5829 ret = status;
5830 ALOGE("%s: compr start failed with err %d", __func__, errno);
5831 goto exit;
5832 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005833 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005834 out->playback_started = 1;
5835 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005836
5837 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5838 popcount(out->channel_mask),
5839 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005840 }
5841 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005842 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005843 return ret;
5844 } else {
5845 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005846 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005847 if (out->muted)
5848 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005849 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5850 __func__, frames, frame_size, bytes_to_write);
5851
Aalique Grahame22e49102018-12-18 14:23:57 -08005852 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005853 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5854 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5855 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005856 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5857 int16_t *src = (int16_t *)buffer;
5858 int16_t *dst = (int16_t *)buffer;
5859
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005860 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005861 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005862 "out_write called for %s use case with wrong properties",
5863 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005864
5865 /*
5866 * FIXME: this can be removed once audio flinger mixer supports
5867 * mono output
5868 */
5869
5870 /*
5871 * Code below goes over each frame in the buffer and adds both
5872 * L and R samples and then divides by 2 to convert to mono
5873 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005874 if (channel_count == 2) {
5875 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5876 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5877 }
5878 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005879 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005880 }
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305881 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005882
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005883 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005884
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005885 if (out->config.rate)
5886 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5887 out->config.rate;
5888
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005889 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005890 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5891
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005892 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005893 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005894 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305895 out->convert_buffer != NULL) {
5896
5897 memcpy_by_audio_format(out->convert_buffer,
5898 out->hal_op_format,
5899 buffer,
5900 out->hal_ip_format,
5901 out->config.period_size * out->config.channels);
5902
5903 ret = pcm_write(out->pcm, out->convert_buffer,
5904 (out->config.period_size *
5905 out->config.channels *
5906 format_to_bitwidth_table[out->hal_op_format]));
5907 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305908 /*
5909 * To avoid underrun in DSP when the application is not pumping
5910 * data at required rate, check for the no. of bytes and ignore
5911 * pcm_write if it is less than actual buffer size.
5912 * It is a work around to a change in compress VOIP driver.
5913 */
5914 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5915 bytes < (out->config.period_size * out->config.channels *
5916 audio_bytes_per_sample(out->format))) {
5917 size_t voip_buf_size =
5918 out->config.period_size * out->config.channels *
5919 audio_bytes_per_sample(out->format);
5920 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5921 __func__, bytes, voip_buf_size);
5922 usleep(((uint64_t)voip_buf_size - bytes) *
5923 1000000 / audio_stream_out_frame_size(stream) /
5924 out_get_sample_rate(&out->stream.common));
5925 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005926 } else {
5927 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5928 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5929 else
5930 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5931 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305932 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005933
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005934 release_out_focus(out);
5935
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305936 if (ret < 0)
5937 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005938 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305939 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005940 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005941 }
5942
5943exit:
Zhou Songc9672822017-08-16 16:01:39 +08005944 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305945 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305946 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305947 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005948 pthread_mutex_unlock(&out->lock);
5949
5950 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005951 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005952 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305953 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305954 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305955 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305956 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305957 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305958 out->standby = true;
5959 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305960 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005961 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5962 /* prevent division-by-zero */
5963 uint32_t stream_size = audio_stream_out_frame_size(stream);
5964 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005965
Dieter Luecking5d57def2018-09-07 14:23:37 +02005966 if ((stream_size == 0) || (srate == 0)) {
5967 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5968 ATRACE_END();
5969 return -EINVAL;
5970 }
5971 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5972 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005973 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305974 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005975 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005976 return ret;
5977 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005978 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005979 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005980 return bytes;
5981}
5982
5983static int out_get_render_position(const struct audio_stream_out *stream,
5984 uint32_t *dsp_frames)
5985{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005986 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005987
5988 if (dsp_frames == NULL)
5989 return -EINVAL;
5990
5991 *dsp_frames = 0;
5992 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005993 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305994
5995 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5996 * this operation and adev_close_output_stream(where out gets reset).
5997 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305998 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005999 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05306000 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006001 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05306002 return 0;
6003 }
6004
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006005 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306006 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306007 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006008 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306009 if (ret < 0)
6010 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006011 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306012 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006013 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306014 if (-ENETRESET == ret) {
6015 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306016 out->card_status = CARD_STATUS_OFFLINE;
6017 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306018 } else if(ret < 0) {
6019 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306020 ret = -EINVAL;
6021 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306022 /*
6023 * Handle corner case where compress session is closed during SSR
6024 * and timestamp is queried
6025 */
6026 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306027 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306028 } else if (out->prev_card_status_offline) {
6029 ALOGE("ERROR: previously sound card was offline,return error");
6030 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306031 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306032 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006033 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306034 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306035 pthread_mutex_unlock(&out->lock);
6036 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006037 } else if (audio_is_linear_pcm(out->format)) {
6038 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006039 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006040 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006041 } else
6042 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006043}
6044
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006045static int out_add_audio_effect(const struct audio_stream *stream __unused,
6046 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006047{
6048 return 0;
6049}
6050
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006051static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6052 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006053{
6054 return 0;
6055}
6056
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006057static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6058 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006059{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306060 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006061}
6062
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006063static int out_get_presentation_position(const struct audio_stream_out *stream,
6064 uint64_t *frames, struct timespec *timestamp)
6065{
6066 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306067 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006068 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006069
Ashish Jain5106d362016-05-11 19:23:33 +05306070 /* below piece of code is not guarded against any lock because audioFliner serializes
6071 * this operation and adev_close_output_stream( where out gets reset).
6072 */
6073 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306074 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006075 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306076 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6077 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6078 return 0;
6079 }
6080
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006081 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006082
Ashish Jain5106d362016-05-11 19:23:33 +05306083 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6084 ret = compress_get_tstamp(out->compr, &dsp_frames,
6085 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006086 // Adjustment accounts for A2dp encoder latency with offload usecases
6087 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006088 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006089 unsigned long offset =
6090 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6091 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6092 }
Ashish Jain5106d362016-05-11 19:23:33 +05306093 ALOGVV("%s rendered frames %ld sample_rate %d",
6094 __func__, dsp_frames, out->sample_rate);
6095 *frames = dsp_frames;
6096 if (ret < 0)
6097 ret = -errno;
6098 if (-ENETRESET == ret) {
6099 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306100 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306101 ret = -EINVAL;
6102 } else
6103 ret = 0;
6104 /* this is the best we can do */
6105 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006106 } else {
6107 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006108 unsigned int avail;
6109 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
6110 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
George Gao62ebc722019-07-29 16:29:44 -07006111
6112 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006113 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006114
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006115 frames_temp = (kernel_buffer_size > avail) ? (kernel_buffer_size - avail) : 0;
6116 if (out->written >= frames_temp)
6117 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006118
Weiyin Jiangd4633762018-03-16 12:05:03 +08006119 // This adjustment accounts for buffering after app processor.
6120 // It is based on estimated DSP latency per use case, rather than exact.
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006121 frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
6122 if (signed_frames >= frames_temp)
6123 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006124
Weiyin Jiangd4633762018-03-16 12:05:03 +08006125 // Adjustment accounts for A2dp encoder latency with non offload usecases
6126 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006127 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006128 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6129 if (signed_frames >= frames_temp)
6130 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006131 }
6132
6133 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006134 *frames = signed_frames;
6135 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006136 }
Eric Laurenta7a33042019-07-10 16:20:22 -07006137 } else if (out->card_status == CARD_STATUS_OFFLINE ||
6138 // audioflinger still needs position updates when A2DP is suspended
6139 is_a2dp_out_device_type(&out->device_list) && audio_extn_a2dp_source_is_suspended()) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306140 *frames = out->written;
6141 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306142 if (is_offload_usecase(out->usecase))
6143 ret = -EINVAL;
6144 else
6145 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006146 }
6147 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006148 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006149 return ret;
6150}
6151
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006152static int out_set_callback(struct audio_stream_out *stream,
6153 stream_callback_t callback, void *cookie)
6154{
6155 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006156 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006157
6158 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006159 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006160 out->client_callback = callback;
6161 out->client_cookie = cookie;
6162 if (out->adsp_hdlr_stream_handle) {
6163 ret = audio_extn_adsp_hdlr_stream_set_callback(
6164 out->adsp_hdlr_stream_handle,
6165 callback,
6166 cookie);
6167 if (ret)
6168 ALOGW("%s:adsp hdlr callback registration failed %d",
6169 __func__, ret);
6170 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006171 pthread_mutex_unlock(&out->lock);
6172 return 0;
6173}
6174
6175static int out_pause(struct audio_stream_out* stream)
6176{
6177 struct stream_out *out = (struct stream_out *)stream;
6178 int status = -ENOSYS;
6179 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006180 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006181 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006182 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006183 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306184 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306185 status = compress_pause(out->compr);
6186
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006187 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006188
Mingming Yin21854652016-04-13 11:54:02 -07006189 if (audio_extn_passthru_is_active()) {
6190 ALOGV("offload use case, pause passthru");
6191 audio_extn_passthru_on_pause(out);
6192 }
6193
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306194 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006195 audio_extn_dts_notify_playback_state(out->usecase, 0,
6196 out->sample_rate, popcount(out->channel_mask),
6197 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006198 }
6199 pthread_mutex_unlock(&out->lock);
6200 }
6201 return status;
6202}
6203
6204static int out_resume(struct audio_stream_out* stream)
6205{
6206 struct stream_out *out = (struct stream_out *)stream;
6207 int status = -ENOSYS;
6208 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006209 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006210 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006211 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006212 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006213 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306214 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306215 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006216 }
6217 if (!status) {
6218 out->offload_state = OFFLOAD_STATE_PLAYING;
6219 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306220 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006221 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6222 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006223 }
6224 pthread_mutex_unlock(&out->lock);
6225 }
6226 return status;
6227}
6228
6229static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6230{
6231 struct stream_out *out = (struct stream_out *)stream;
6232 int status = -ENOSYS;
6233 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006234 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006235 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006236 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6237 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6238 else
6239 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6240 pthread_mutex_unlock(&out->lock);
6241 }
6242 return status;
6243}
6244
6245static int out_flush(struct audio_stream_out* stream)
6246{
6247 struct stream_out *out = (struct stream_out *)stream;
6248 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006249 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006250 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006251 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006252 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6253 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006254 } else {
6255 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6256 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006257 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006258 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006259 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006260 return 0;
6261 }
6262 return -ENOSYS;
6263}
6264
Haynes Mathew George16081042017-05-31 17:16:49 -07006265static int out_stop(const struct audio_stream_out* stream)
6266{
6267 struct stream_out *out = (struct stream_out *)stream;
6268 struct audio_device *adev = out->dev;
6269 int ret = -ENOSYS;
6270
6271 ALOGV("%s", __func__);
6272 pthread_mutex_lock(&adev->lock);
6273 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6274 out->playback_started && out->pcm != NULL) {
6275 pcm_stop(out->pcm);
6276 ret = stop_output_stream(out);
6277 out->playback_started = false;
6278 }
6279 pthread_mutex_unlock(&adev->lock);
6280 return ret;
6281}
6282
6283static int out_start(const struct audio_stream_out* stream)
6284{
6285 struct stream_out *out = (struct stream_out *)stream;
6286 struct audio_device *adev = out->dev;
6287 int ret = -ENOSYS;
6288
6289 ALOGV("%s", __func__);
6290 pthread_mutex_lock(&adev->lock);
6291 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6292 !out->playback_started && out->pcm != NULL) {
6293 ret = start_output_stream(out);
6294 if (ret == 0) {
6295 out->playback_started = true;
6296 }
6297 }
6298 pthread_mutex_unlock(&adev->lock);
6299 return ret;
6300}
6301
6302/*
6303 * Modify config->period_count based on min_size_frames
6304 */
6305static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6306{
6307 int periodCountRequested = (min_size_frames + config->period_size - 1)
6308 / config->period_size;
6309 int periodCount = MMAP_PERIOD_COUNT_MIN;
6310
6311 ALOGV("%s original config.period_size = %d config.period_count = %d",
6312 __func__, config->period_size, config->period_count);
6313
6314 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6315 periodCount *= 2;
6316 }
6317 config->period_count = periodCount;
6318
6319 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6320}
6321
Phil Burkfe17efd2019-03-25 10:23:35 -07006322// Read offset for the positional timestamp from a persistent vendor property.
6323// This is to workaround apparent inaccuracies in the timing information that
6324// is used by the AAudio timing model. The inaccuracies can cause glitches.
6325static int64_t get_mmap_out_time_offset() {
6326 const int32_t kDefaultOffsetMicros = 0;
6327 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006328 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006329 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6330 return mmap_time_offset_micros * (int64_t)1000;
6331}
6332
Haynes Mathew George16081042017-05-31 17:16:49 -07006333static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6334 int32_t min_size_frames,
6335 struct audio_mmap_buffer_info *info)
6336{
6337 struct stream_out *out = (struct stream_out *)stream;
6338 struct audio_device *adev = out->dev;
6339 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006340 unsigned int offset1 = 0;
6341 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006342 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006343 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006344 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006345
Arun Mirpuri5d170872019-03-26 13:21:31 -07006346 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306347 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006348 pthread_mutex_lock(&adev->lock);
6349
Sharad Sanglec6f32552018-05-04 16:15:38 +05306350 if (CARD_STATUS_OFFLINE == out->card_status ||
6351 CARD_STATUS_OFFLINE == adev->card_status) {
6352 ALOGW("out->card_status or adev->card_status offline, try again");
6353 ret = -EIO;
6354 goto exit;
6355 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006356 if (info == NULL || min_size_frames == 0) {
6357 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6358 ret = -EINVAL;
6359 goto exit;
6360 }
6361 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6362 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6363 ret = -ENOSYS;
6364 goto exit;
6365 }
6366 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6367 if (out->pcm_device_id < 0) {
6368 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6369 __func__, out->pcm_device_id, out->usecase);
6370 ret = -EINVAL;
6371 goto exit;
6372 }
6373
6374 adjust_mmap_period_count(&out->config, min_size_frames);
6375
Arun Mirpuri5d170872019-03-26 13:21:31 -07006376 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006377 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6378 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6379 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306380 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306381 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6382 out->card_status = CARD_STATUS_OFFLINE;
6383 adev->card_status = CARD_STATUS_OFFLINE;
6384 ret = -EIO;
6385 goto exit;
6386 }
6387
Haynes Mathew George16081042017-05-31 17:16:49 -07006388 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6389 step = "open";
6390 ret = -ENODEV;
6391 goto exit;
6392 }
6393 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6394 if (ret < 0) {
6395 step = "begin";
6396 goto exit;
6397 }
juyuchen626833d2019-06-04 16:48:02 +08006398
6399 info->flags = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006400 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006401 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006402 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006403 ret = platform_get_mmap_data_fd(adev->platform,
6404 out->pcm_device_id, 0 /*playback*/,
6405 &info->shared_memory_fd,
6406 &mmap_size);
6407 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006408 // Fall back to non exclusive mode
6409 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6410 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006411 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6412 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6413
Arun Mirpuri5d170872019-03-26 13:21:31 -07006414 if (mmap_size < buffer_size) {
6415 step = "mmap";
6416 goto exit;
6417 }
juyuchen626833d2019-06-04 16:48:02 +08006418 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006419 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006420 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006421 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006422
6423 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6424 if (ret < 0) {
6425 step = "commit";
6426 goto exit;
6427 }
6428
Phil Burkfe17efd2019-03-25 10:23:35 -07006429 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6430
Haynes Mathew George16081042017-05-31 17:16:49 -07006431 out->standby = false;
6432 ret = 0;
6433
Arun Mirpuri5d170872019-03-26 13:21:31 -07006434 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006435 __func__, info->shared_memory_address, info->buffer_size_frames);
6436
6437exit:
6438 if (ret != 0) {
6439 if (out->pcm == NULL) {
6440 ALOGE("%s: %s - %d", __func__, step, ret);
6441 } else {
6442 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6443 pcm_close(out->pcm);
6444 out->pcm = NULL;
6445 }
6446 }
6447 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306448 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006449 return ret;
6450}
6451
6452static int out_get_mmap_position(const struct audio_stream_out *stream,
6453 struct audio_mmap_position *position)
6454{
6455 struct stream_out *out = (struct stream_out *)stream;
6456 ALOGVV("%s", __func__);
6457 if (position == NULL) {
6458 return -EINVAL;
6459 }
6460 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006461 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006462 return -ENOSYS;
6463 }
6464 if (out->pcm == NULL) {
6465 return -ENOSYS;
6466 }
6467
6468 struct timespec ts = { 0, 0 };
6469 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6470 if (ret < 0) {
6471 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6472 return ret;
6473 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006474 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6475 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006476 return 0;
6477}
6478
6479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006480/** audio_stream_in implementation **/
6481static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6482{
6483 struct stream_in *in = (struct stream_in *)stream;
6484
6485 return in->config.rate;
6486}
6487
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006488static int in_set_sample_rate(struct audio_stream *stream __unused,
6489 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006490{
6491 return -ENOSYS;
6492}
6493
6494static size_t in_get_buffer_size(const struct audio_stream *stream)
6495{
6496 struct stream_in *in = (struct stream_in *)stream;
6497
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006498 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6499 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006500 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6501 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306502 else if(audio_extn_cin_attached_usecase(in))
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306503 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006504
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006505 return in->config.period_size * in->af_period_multiplier *
6506 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006507}
6508
6509static uint32_t in_get_channels(const struct audio_stream *stream)
6510{
6511 struct stream_in *in = (struct stream_in *)stream;
6512
6513 return in->channel_mask;
6514}
6515
6516static audio_format_t in_get_format(const struct audio_stream *stream)
6517{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006518 struct stream_in *in = (struct stream_in *)stream;
6519
6520 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006521}
6522
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006523static int in_set_format(struct audio_stream *stream __unused,
6524 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006525{
6526 return -ENOSYS;
6527}
6528
6529static int in_standby(struct audio_stream *stream)
6530{
6531 struct stream_in *in = (struct stream_in *)stream;
6532 struct audio_device *adev = in->dev;
6533 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306534 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6535 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006536 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306537
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006538 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006539 if (!in->standby && in->is_st_session) {
6540 ALOGD("%s: sound trigger pcm stop lab", __func__);
6541 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006542 if (adev->num_va_sessions > 0)
6543 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006544 in->standby = 1;
6545 }
6546
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006547 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006548 if (adev->adm_deregister_stream)
6549 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6550
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006551 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006552 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006553 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006554 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006555 voice_extn_compress_voip_close_input_stream(stream);
6556 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006557 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6558 do_stop = in->capture_started;
6559 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006560 if (in->mmap_shared_memory_fd >= 0) {
6561 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6562 __func__, in->mmap_shared_memory_fd);
6563 close(in->mmap_shared_memory_fd);
6564 in->mmap_shared_memory_fd = -1;
6565 }
Zhou Songa8895042016-07-05 17:54:22 +08006566 } else {
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306567 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05306568 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006569 }
6570
Arun Mirpuri5d170872019-03-26 13:21:31 -07006571 if (in->pcm) {
6572 ATRACE_BEGIN("pcm_in_close");
6573 pcm_close(in->pcm);
6574 ATRACE_END();
6575 in->pcm = NULL;
6576 }
6577
Carter Hsu2e429db2019-05-14 18:50:52 +08006578 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006579 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006580
George Gao3018ede2019-10-23 13:23:00 -07006581 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6582 if (adev->num_va_sessions > 0)
6583 adev->num_va_sessions--;
6584 }
Quinn Malef6050362019-01-30 15:55:40 -08006585
Eric Laurent150dbfe2013-02-27 14:31:02 -08006586 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006587 }
6588 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006589 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006590 return status;
6591}
6592
Aalique Grahame22e49102018-12-18 14:23:57 -08006593static int in_dump(const struct audio_stream *stream,
6594 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006595{
Aalique Grahame22e49102018-12-18 14:23:57 -08006596 struct stream_in *in = (struct stream_in *)stream;
6597
6598 // We try to get the lock for consistency,
6599 // but it isn't necessary for these variables.
6600 // If we're not in standby, we may be blocked on a read.
6601 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6602 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6603 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6604 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6605
6606 if (locked) {
6607 pthread_mutex_unlock(&in->lock);
6608 }
6609
6610 // dump error info
6611 (void)error_log_dump(
6612 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006614 return 0;
6615}
6616
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306617static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6618{
6619 if (!stream || !parms)
6620 return;
6621
6622 struct stream_in *in = (struct stream_in *)stream;
6623 struct audio_device *adev = in->dev;
6624
6625 card_status_t status;
6626 int card;
6627 if (parse_snd_card_status(parms, &card, &status) < 0)
6628 return;
6629
6630 pthread_mutex_lock(&adev->lock);
6631 bool valid_cb = (card == adev->snd_card);
6632 pthread_mutex_unlock(&adev->lock);
6633
6634 if (!valid_cb)
6635 return;
6636
6637 lock_input_stream(in);
6638 if (in->card_status != status)
6639 in->card_status = status;
6640 pthread_mutex_unlock(&in->lock);
6641
6642 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6643 use_case_table[in->usecase],
6644 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6645
6646 // a better solution would be to report error back to AF and let
6647 // it put the stream to standby
6648 if (status == CARD_STATUS_OFFLINE)
6649 in_standby(&in->stream.common);
6650
6651 return;
6652}
6653
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006654int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006655 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006656 audio_source_t source)
6657{
6658 struct audio_device *adev = in->dev;
6659 int ret = 0;
6660
6661 lock_input_stream(in);
6662 pthread_mutex_lock(&adev->lock);
6663
6664 /* no audio source uses val == 0 */
6665 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6666 in->source = source;
6667 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6668 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6669 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6670 (in->config.rate == 8000 || in->config.rate == 16000 ||
6671 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6672 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6673 ret = voice_extn_compress_voip_open_input_stream(in);
6674 if (ret != 0) {
6675 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6676 __func__, ret);
6677 }
6678 }
6679 }
6680
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006681 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6682 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006683 // Workaround: If routing to an non existing usb device, fail gracefully
6684 // The routing request will otherwise block during 10 second
6685 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006686 struct str_parms *usb_addr =
6687 str_parms_create_str(get_usb_device_address(devices));
6688 if (is_usb_in_device_type(devices) && usb_addr &&
6689 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006690 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6691 ret = -ENOSYS;
6692 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006693 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006694 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006695 if (!in->standby && !in->is_st_session) {
6696 ALOGV("update input routing change");
6697 // inform adm before actual routing to prevent glitches.
6698 if (adev->adm_on_routing_change) {
6699 adev->adm_on_routing_change(adev->adm_data,
6700 in->capture_handle);
6701 ret = select_devices(adev, in->usecase);
6702 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6703 adev->adm_routing_changed = true;
6704 }
6705 }
6706 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006707 if (usb_addr)
6708 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006709 }
6710 pthread_mutex_unlock(&adev->lock);
6711 pthread_mutex_unlock(&in->lock);
6712
6713 ALOGD("%s: exit: status(%d)", __func__, ret);
6714 return ret;
6715}
6716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006717static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6718{
6719 struct stream_in *in = (struct stream_in *)stream;
6720 struct audio_device *adev = in->dev;
6721 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006722 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006723 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006724
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306725 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006726 parms = str_parms_create_str(kvpairs);
6727
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306728 if (!parms)
6729 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006730 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006731 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006732
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006733 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6734 if (ret >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306735 strlcpy(in->profile, value, sizeof(in->profile));
6736 ALOGV("updating stream profile with value '%s'", in->profile);
6737 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6738 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006739 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306740 in->sample_rate, in->bit_width,
6741 in->profile, &in->app_type_cfg);
6742 }
6743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006744 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006745 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006746
6747 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306748error:
Eric Laurent994a6932013-07-17 11:51:42 -07006749 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006750 return ret;
6751}
6752
6753static char* in_get_parameters(const struct audio_stream *stream,
6754 const char *keys)
6755{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006756 struct stream_in *in = (struct stream_in *)stream;
6757 struct str_parms *query = str_parms_create_str(keys);
6758 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006759 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006760
6761 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006762 if (reply) {
6763 str_parms_destroy(reply);
6764 }
6765 if (query) {
6766 str_parms_destroy(query);
6767 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006768 ALOGE("in_get_parameters: failed to create query or reply");
6769 return NULL;
6770 }
6771
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006772 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006773
6774 voice_extn_in_get_parameters(in, query, reply);
6775
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006776 stream_get_parameter_channels(query, reply,
6777 &in->supported_channel_masks[0]);
6778 stream_get_parameter_formats(query, reply,
6779 &in->supported_formats[0]);
6780 stream_get_parameter_rates(query, reply,
6781 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006782 str = str_parms_to_str(reply);
6783 str_parms_destroy(query);
6784 str_parms_destroy(reply);
6785
6786 ALOGV("%s: exit: returns - %s", __func__, str);
6787 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006788}
6789
Aalique Grahame22e49102018-12-18 14:23:57 -08006790static int in_set_gain(struct audio_stream_in *stream,
6791 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006792{
Aalique Grahame22e49102018-12-18 14:23:57 -08006793 struct stream_in *in = (struct stream_in *)stream;
6794 char mixer_ctl_name[128];
6795 struct mixer_ctl *ctl;
6796 int ctl_value;
6797
6798 ALOGV("%s: gain %f", __func__, gain);
6799
6800 if (stream == NULL)
6801 return -EINVAL;
6802
6803 /* in_set_gain() only used to silence MMAP capture for now */
6804 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6805 return -ENOSYS;
6806
6807 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6808
6809 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6810 if (!ctl) {
6811 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6812 __func__, mixer_ctl_name);
6813 return -ENOSYS;
6814 }
6815
6816 if (gain < RECORD_GAIN_MIN)
6817 gain = RECORD_GAIN_MIN;
6818 else if (gain > RECORD_GAIN_MAX)
6819 gain = RECORD_GAIN_MAX;
6820 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6821
6822 mixer_ctl_set_value(ctl, 0, ctl_value);
6823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006824 return 0;
6825}
6826
6827static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6828 size_t bytes)
6829{
6830 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306831
6832 if (in == NULL) {
6833 ALOGE("%s: stream_in ptr is NULL", __func__);
6834 return -EINVAL;
6835 }
6836
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006837 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306838 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306839 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006840
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006841 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306842
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006843 if (in->is_st_session) {
6844 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6845 /* Read from sound trigger HAL */
6846 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006847 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006848 if (adev->num_va_sessions < UINT_MAX)
6849 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006850 in->standby = 0;
6851 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006852 pthread_mutex_unlock(&in->lock);
6853 return bytes;
6854 }
6855
Haynes Mathew George16081042017-05-31 17:16:49 -07006856 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6857 ret = -ENOSYS;
6858 goto exit;
6859 }
6860
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006861 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6862 !in->standby && adev->adm_routing_changed) {
6863 ret = -ENOSYS;
6864 goto exit;
6865 }
6866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006867 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006868 pthread_mutex_lock(&adev->lock);
6869 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6870 ret = voice_extn_compress_voip_start_input_stream(in);
6871 else
6872 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006873 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6874 if (adev->num_va_sessions < UINT_MAX)
6875 adev->num_va_sessions++;
6876 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006877 pthread_mutex_unlock(&adev->lock);
6878 if (ret != 0) {
6879 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006880 }
6881 in->standby = 0;
6882 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006883
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306884 /* Avoid read if capture_stopped is set */
6885 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6886 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6887 ret = -EINVAL;
6888 goto exit;
6889 }
6890
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006891 // what's the duration requested by the client?
6892 long ns = 0;
6893
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306894 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006895 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6896 in->config.rate;
6897
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006898 ret = request_in_focus(in, ns);
6899 if (ret != 0)
6900 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006901 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006902
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306903 if (audio_extn_cin_attached_usecase(in)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306904 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6905 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306906 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006907 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306908 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006909 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006910 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006911 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006912 } else if (audio_extn_ffv_get_stream() == in) {
6913 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306914 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006915 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306916 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6917 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6918 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6919 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306920 ret = -EINVAL;
6921 goto exit;
6922 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306923 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306924 ret = -errno;
6925 }
6926 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306927 /* bytes read is always set to bytes for non compress usecases */
6928 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006929 }
6930
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006931 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006933 /*
Quinn Malef6050362019-01-30 15:55:40 -08006934 * Instead of writing zeroes here, we could trust the hardware to always
6935 * provide zeroes when muted. This is also muted with voice recognition
6936 * usecases so that other clients do not have access to voice recognition
6937 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006938 */
Quinn Malef6050362019-01-30 15:55:40 -08006939 if ((ret == 0 && voice_get_mic_mute(adev) &&
6940 !voice_is_in_call_rec_stream(in) &&
6941 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6942 (adev->num_va_sessions &&
6943 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6944 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6945 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006946 memset(buffer, 0, bytes);
6947
6948exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306949 frame_size = audio_stream_in_frame_size(stream);
6950 if (frame_size > 0)
6951 in->frames_read += bytes_read/frame_size;
6952
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006953 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306954 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006955 pthread_mutex_unlock(&in->lock);
6956
6957 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306958 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306959 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306960 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306961 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306962 in->standby = true;
6963 }
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05306964 if (!audio_extn_cin_attached_usecase(in)) {
Sharad Sangled17c9122017-03-20 15:58:52 +05306965 bytes_read = bytes;
6966 memset(buffer, 0, bytes);
6967 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006968 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006969 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6970 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006971 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306972 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306973 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006974 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306975 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006976}
6977
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006978static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006979{
6980 return 0;
6981}
6982
Aalique Grahame22e49102018-12-18 14:23:57 -08006983static int in_get_capture_position(const struct audio_stream_in *stream,
6984 int64_t *frames, int64_t *time)
6985{
6986 if (stream == NULL || frames == NULL || time == NULL) {
6987 return -EINVAL;
6988 }
6989 struct stream_in *in = (struct stream_in *)stream;
6990 int ret = -ENOSYS;
6991
6992 lock_input_stream(in);
6993 // note: ST sessions do not close the alsa pcm driver synchronously
6994 // on standby. Therefore, we may return an error even though the
6995 // pcm stream is still opened.
6996 if (in->standby) {
6997 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6998 "%s stream in standby but pcm not NULL for non ST session", __func__);
6999 goto exit;
7000 }
7001 if (in->pcm) {
7002 struct timespec timestamp;
7003 unsigned int avail;
7004 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
7005 *frames = in->frames_read + avail;
7006 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
7007 ret = 0;
7008 }
7009 }
7010exit:
7011 pthread_mutex_unlock(&in->lock);
7012 return ret;
7013}
7014
Carter Hsu2e429db2019-05-14 18:50:52 +08007015static int in_update_effect_list(bool add, effect_handle_t effect,
7016 struct listnode *head)
7017{
7018 struct listnode *node;
7019 struct in_effect_list *elist = NULL;
7020 struct in_effect_list *target = NULL;
7021 int ret = 0;
7022
7023 if (!head)
7024 return ret;
7025
7026 list_for_each(node, head) {
7027 elist = node_to_item(node, struct in_effect_list, list);
7028 if (elist->handle == effect) {
7029 target = elist;
7030 break;
7031 }
7032 }
7033
7034 if (add) {
7035 if (target) {
7036 ALOGD("effect %p already exist", effect);
7037 return ret;
7038 }
7039
7040 target = (struct in_effect_list *)
7041 calloc(1, sizeof(struct in_effect_list));
7042
7043 if (!target) {
7044 ALOGE("%s:fail to allocate memory", __func__);
7045 return -ENOMEM;
7046 }
7047
7048 target->handle = effect;
7049 list_add_tail(head, &target->list);
7050 } else {
7051 if (target) {
7052 list_remove(&target->list);
7053 free(target);
7054 }
7055 }
7056
7057 return ret;
7058}
7059
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007060static int add_remove_audio_effect(const struct audio_stream *stream,
7061 effect_handle_t effect,
7062 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007063{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007064 struct stream_in *in = (struct stream_in *)stream;
7065 int status = 0;
7066 effect_descriptor_t desc;
7067
7068 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007069 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7070
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007071 if (status != 0)
7072 return status;
7073
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007074 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007075 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007076 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007077 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7078 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007079 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007080
7081 in_update_effect_list(enable, effect, &in->aec_list);
7082 enable = !list_empty(&in->aec_list);
7083 if (enable == in->enable_aec)
7084 goto exit;
7085
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007086 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007087 ALOGD("AEC enable %d", enable);
7088
Aalique Grahame22e49102018-12-18 14:23:57 -08007089 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7090 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7091 in->dev->enable_voicerx = enable;
7092 struct audio_usecase *usecase;
7093 struct listnode *node;
7094 list_for_each(node, &in->dev->usecase_list) {
7095 usecase = node_to_item(node, struct audio_usecase, list);
7096 if (usecase->type == PCM_PLAYBACK)
7097 select_devices(in->dev, usecase->id);
7098 }
7099 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007100 if (!in->standby) {
7101 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7102 select_devices(in->dev, in->usecase);
7103 }
7104
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007105 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007106 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7107
7108 in_update_effect_list(enable, effect, &in->ns_list);
7109 enable = !list_empty(&in->ns_list);
7110 if (enable == in->enable_ns)
7111 goto exit;
7112
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007113 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007114 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007115 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007116 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7117 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007118 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7119 select_devices(in->dev, in->usecase);
7120 } else
7121 select_devices(in->dev, in->usecase);
7122 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007123 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007124exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007125 pthread_mutex_unlock(&in->dev->lock);
7126 pthread_mutex_unlock(&in->lock);
7127
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007128 return 0;
7129}
7130
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007131static int in_add_audio_effect(const struct audio_stream *stream,
7132 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007133{
Eric Laurent994a6932013-07-17 11:51:42 -07007134 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007135 return add_remove_audio_effect(stream, effect, true);
7136}
7137
7138static int in_remove_audio_effect(const struct audio_stream *stream,
7139 effect_handle_t effect)
7140{
Eric Laurent994a6932013-07-17 11:51:42 -07007141 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007142 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007143}
7144
Derek Chenf939fb72018-11-13 13:34:41 -08007145streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7146 audio_io_handle_t input)
7147{
7148 struct listnode *node;
7149
7150 list_for_each(node, &dev->active_inputs_list) {
7151 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7152 streams_input_ctxt_t,
7153 list);
7154 if (in_ctxt->input->capture_handle == input) {
7155 return in_ctxt;
7156 }
7157 }
7158 return NULL;
7159}
7160
7161streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7162 audio_io_handle_t output)
7163{
7164 struct listnode *node;
7165
7166 list_for_each(node, &dev->active_outputs_list) {
7167 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7168 streams_output_ctxt_t,
7169 list);
7170 if (out_ctxt->output->handle == output) {
7171 return out_ctxt;
7172 }
7173 }
7174 return NULL;
7175}
7176
Haynes Mathew George16081042017-05-31 17:16:49 -07007177static int in_stop(const struct audio_stream_in* stream)
7178{
7179 struct stream_in *in = (struct stream_in *)stream;
7180 struct audio_device *adev = in->dev;
7181
7182 int ret = -ENOSYS;
7183 ALOGV("%s", __func__);
7184 pthread_mutex_lock(&adev->lock);
7185 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7186 in->capture_started && in->pcm != NULL) {
7187 pcm_stop(in->pcm);
7188 ret = stop_input_stream(in);
7189 in->capture_started = false;
7190 }
7191 pthread_mutex_unlock(&adev->lock);
7192 return ret;
7193}
7194
7195static int in_start(const struct audio_stream_in* stream)
7196{
7197 struct stream_in *in = (struct stream_in *)stream;
7198 struct audio_device *adev = in->dev;
7199 int ret = -ENOSYS;
7200
7201 ALOGV("%s in %p", __func__, in);
7202 pthread_mutex_lock(&adev->lock);
7203 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7204 !in->capture_started && in->pcm != NULL) {
7205 if (!in->capture_started) {
7206 ret = start_input_stream(in);
7207 if (ret == 0) {
7208 in->capture_started = true;
7209 }
7210 }
7211 }
7212 pthread_mutex_unlock(&adev->lock);
7213 return ret;
7214}
7215
Phil Burke0a86d12019-02-16 22:28:11 -08007216// Read offset for the positional timestamp from a persistent vendor property.
7217// This is to workaround apparent inaccuracies in the timing information that
7218// is used by the AAudio timing model. The inaccuracies can cause glitches.
7219static int64_t in_get_mmap_time_offset() {
7220 const int32_t kDefaultOffsetMicros = 0;
7221 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007222 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007223 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7224 return mmap_time_offset_micros * (int64_t)1000;
7225}
7226
Haynes Mathew George16081042017-05-31 17:16:49 -07007227static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7228 int32_t min_size_frames,
7229 struct audio_mmap_buffer_info *info)
7230{
7231 struct stream_in *in = (struct stream_in *)stream;
7232 struct audio_device *adev = in->dev;
7233 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007234 unsigned int offset1 = 0;
7235 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007236 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007237 uint32_t mmap_size = 0;
7238 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007239
7240 pthread_mutex_lock(&adev->lock);
7241 ALOGV("%s in %p", __func__, in);
7242
Sharad Sanglec6f32552018-05-04 16:15:38 +05307243 if (CARD_STATUS_OFFLINE == in->card_status||
7244 CARD_STATUS_OFFLINE == adev->card_status) {
7245 ALOGW("in->card_status or adev->card_status offline, try again");
7246 ret = -EIO;
7247 goto exit;
7248 }
7249
Haynes Mathew George16081042017-05-31 17:16:49 -07007250 if (info == NULL || min_size_frames == 0) {
7251 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7252 ret = -EINVAL;
7253 goto exit;
7254 }
7255 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7256 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7257 ALOGV("%s in %p", __func__, in);
7258 ret = -ENOSYS;
7259 goto exit;
7260 }
7261 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7262 if (in->pcm_device_id < 0) {
7263 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7264 __func__, in->pcm_device_id, in->usecase);
7265 ret = -EINVAL;
7266 goto exit;
7267 }
7268
7269 adjust_mmap_period_count(&in->config, min_size_frames);
7270
7271 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7272 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7273 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7274 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307275 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307276 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7277 in->card_status = CARD_STATUS_OFFLINE;
7278 adev->card_status = CARD_STATUS_OFFLINE;
7279 ret = -EIO;
7280 goto exit;
7281 }
7282
Haynes Mathew George16081042017-05-31 17:16:49 -07007283 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7284 step = "open";
7285 ret = -ENODEV;
7286 goto exit;
7287 }
7288
7289 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7290 if (ret < 0) {
7291 step = "begin";
7292 goto exit;
7293 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007294
juyuchen626833d2019-06-04 16:48:02 +08007295 info->flags = 0;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007296 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7297 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7298 info->burst_size_frames = in->config.period_size;
7299 ret = platform_get_mmap_data_fd(adev->platform,
7300 in->pcm_device_id, 1 /*capture*/,
7301 &info->shared_memory_fd,
7302 &mmap_size);
7303 if (ret < 0) {
7304 // Fall back to non exclusive mode
7305 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7306 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007307 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7308 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7309
Arun Mirpuri5d170872019-03-26 13:21:31 -07007310 if (mmap_size < buffer_size) {
7311 step = "mmap";
7312 goto exit;
7313 }
juyuchen626833d2019-06-04 16:48:02 +08007314 info->flags |= AUDIO_MMAP_APPLICATION_SHAREABLE;
Arun Mirpuri5d170872019-03-26 13:21:31 -07007315 }
7316
7317 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007318
7319 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7320 if (ret < 0) {
7321 step = "commit";
7322 goto exit;
7323 }
7324
Phil Burke0a86d12019-02-16 22:28:11 -08007325 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7326
Haynes Mathew George16081042017-05-31 17:16:49 -07007327 in->standby = false;
7328 ret = 0;
7329
7330 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7331 __func__, info->shared_memory_address, info->buffer_size_frames);
7332
7333exit:
7334 if (ret != 0) {
7335 if (in->pcm == NULL) {
7336 ALOGE("%s: %s - %d", __func__, step, ret);
7337 } else {
7338 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7339 pcm_close(in->pcm);
7340 in->pcm = NULL;
7341 }
7342 }
7343 pthread_mutex_unlock(&adev->lock);
7344 return ret;
7345}
7346
7347static int in_get_mmap_position(const struct audio_stream_in *stream,
7348 struct audio_mmap_position *position)
7349{
7350 struct stream_in *in = (struct stream_in *)stream;
7351 ALOGVV("%s", __func__);
7352 if (position == NULL) {
7353 return -EINVAL;
7354 }
7355 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7356 return -ENOSYS;
7357 }
7358 if (in->pcm == NULL) {
7359 return -ENOSYS;
7360 }
7361 struct timespec ts = { 0, 0 };
7362 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7363 if (ret < 0) {
7364 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7365 return ret;
7366 }
Phil Burke0a86d12019-02-16 22:28:11 -08007367 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7368 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007369 return 0;
7370}
7371
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307372static int in_get_active_microphones(const struct audio_stream_in *stream,
7373 struct audio_microphone_characteristic_t *mic_array,
7374 size_t *mic_count) {
7375 struct stream_in *in = (struct stream_in *)stream;
7376 struct audio_device *adev = in->dev;
7377 ALOGVV("%s", __func__);
7378
7379 lock_input_stream(in);
7380 pthread_mutex_lock(&adev->lock);
7381 int ret = platform_get_active_microphones(adev->platform,
7382 audio_channel_count_from_in_mask(in->channel_mask),
7383 in->usecase, mic_array, mic_count);
7384 pthread_mutex_unlock(&adev->lock);
7385 pthread_mutex_unlock(&in->lock);
7386
7387 return ret;
7388}
7389
7390static int adev_get_microphones(const struct audio_hw_device *dev,
7391 struct audio_microphone_characteristic_t *mic_array,
7392 size_t *mic_count) {
7393 struct audio_device *adev = (struct audio_device *)dev;
7394 ALOGVV("%s", __func__);
7395
7396 pthread_mutex_lock(&adev->lock);
7397 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7398 pthread_mutex_unlock(&adev->lock);
7399
7400 return ret;
7401}
juyuchendb308c22019-01-21 11:57:17 -07007402
7403static void in_update_sink_metadata(struct audio_stream_in *stream,
7404 const struct sink_metadata *sink_metadata) {
7405
7406 if (stream == NULL
7407 || sink_metadata == NULL
7408 || sink_metadata->tracks == NULL) {
7409 return;
7410 }
7411
7412 int error = 0;
7413 struct stream_in *in = (struct stream_in *)stream;
7414 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007415 struct listnode devices;
7416
7417 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007418
7419 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007420 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007421
7422 lock_input_stream(in);
7423 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007424 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007425
7426 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007427 && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007428 && adev->voice_tx_output != NULL) {
7429 /* Use the rx device from afe-proxy record to route voice call because
7430 there is no routing if tx device is on primary hal and rx device
7431 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007432 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007433
7434 if (!voice_is_call_state_active(adev)) {
7435 if (adev->mode == AUDIO_MODE_IN_CALL) {
7436 adev->current_call_output = adev->voice_tx_output;
7437 error = voice_start_call(adev);
7438 if (error != 0)
7439 ALOGE("%s: start voice call failed %d", __func__, error);
7440 }
7441 } else {
7442 adev->current_call_output = adev->voice_tx_output;
7443 voice_update_devices_for_all_voice_usecases(adev);
7444 }
7445 }
7446
7447 pthread_mutex_unlock(&adev->lock);
7448 pthread_mutex_unlock(&in->lock);
7449}
7450
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307451int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007452 audio_io_handle_t handle,
7453 audio_devices_t devices,
7454 audio_output_flags_t flags,
7455 struct audio_config *config,
7456 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007457 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007458{
7459 struct audio_device *adev = (struct audio_device *)dev;
7460 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307461 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007462 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007463 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307464 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007465 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7466 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7467 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7468 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007469 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007470 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7471 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007472 bool force_haptic_path =
7473 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007474 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007475
kunleizdff872d2018-08-20 14:40:33 +08007476 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007477 is_usb_dev = false;
7478 devices = AUDIO_DEVICE_OUT_SPEAKER;
7479 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7480 __func__, devices);
Mingshu Pangdbd20562019-11-25 18:04:39 +08007481 if (config->format == AUDIO_FORMAT_DEFAULT)
7482 config->format = AUDIO_FORMAT_PCM_16_BIT;
7483 if (config->sample_rate == 0)
7484 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7485 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7486 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
kunleizd6a9e0c2018-07-30 15:38:52 +08007487 }
7488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007489 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307490
Rahul Sharma99770982019-03-06 17:05:26 +05307491 pthread_mutex_lock(&adev->lock);
7492 if (out_get_stream(adev, handle) != NULL) {
7493 ALOGW("%s, output stream already opened", __func__);
7494 ret = -EEXIST;
7495 }
7496 pthread_mutex_unlock(&adev->lock);
7497 if (ret)
7498 return ret;
7499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007500 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7501
Mingming Yin3a941d42016-02-17 18:08:05 -08007502 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007503 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7504 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307505
7506
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007507 if (!out) {
7508 return -ENOMEM;
7509 }
7510
Haynes Mathew George204045b2015-02-25 20:32:03 -08007511 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007512 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307513 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007514 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007515 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7516
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007517 if (devices == AUDIO_DEVICE_NONE)
7518 devices = AUDIO_DEVICE_OUT_SPEAKER;
7519
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007520 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007521 list_init(&out->device_list);
7522 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007523 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007524 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007525 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307526 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307527 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7528 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7529 else
7530 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007531 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007532 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007533 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307534 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307535 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307536 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007537 out->hal_output_suspend_supported = 0;
7538 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307539 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307540 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307541 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007542 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007543
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307544 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307545 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007546 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7547
Aalique Grahame22e49102018-12-18 14:23:57 -08007548 if (direct_dev &&
7549 (audio_is_linear_pcm(out->format) ||
7550 config->format == AUDIO_FORMAT_DEFAULT) &&
7551 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7552 audio_format_t req_format = config->format;
7553 audio_channel_mask_t req_channel_mask = config->channel_mask;
7554 uint32_t req_sample_rate = config->sample_rate;
7555
7556 pthread_mutex_lock(&adev->lock);
7557 if (is_hdmi) {
7558 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7559 ret = read_hdmi_sink_caps(out);
7560 if (config->sample_rate == 0)
7561 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7562 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7563 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7564 if (config->format == AUDIO_FORMAT_DEFAULT)
7565 config->format = AUDIO_FORMAT_PCM_16_BIT;
7566 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007567 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7568 &config->format,
7569 &out->supported_formats[0],
7570 MAX_SUPPORTED_FORMATS,
7571 &config->channel_mask,
7572 &out->supported_channel_masks[0],
7573 MAX_SUPPORTED_CHANNEL_MASKS,
7574 &config->sample_rate,
7575 &out->supported_sample_rates[0],
7576 MAX_SUPPORTED_SAMPLE_RATES);
7577 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007578 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007579
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007580 pthread_mutex_unlock(&adev->lock);
7581 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007582 if (ret == -ENOSYS) {
7583 /* ignore and go with default */
7584 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007585 }
7586 // For MMAP NO IRQ, allow conversions in ADSP
7587 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7588 goto error_open;
7589 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007590 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007591 goto error_open;
7592 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007593
7594 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7595 config->sample_rate = req_sample_rate;
7596 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7597 config->channel_mask = req_channel_mask;
7598 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7599 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007600 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007601
7602 out->sample_rate = config->sample_rate;
7603 out->channel_mask = config->channel_mask;
7604 out->format = config->format;
7605 if (is_hdmi) {
7606 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7607 out->config = pcm_config_hdmi_multi;
7608 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7609 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7610 out->config = pcm_config_mmap_playback;
7611 out->stream.start = out_start;
7612 out->stream.stop = out_stop;
7613 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7614 out->stream.get_mmap_position = out_get_mmap_position;
7615 } else {
7616 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7617 out->config = pcm_config_hifi;
7618 }
7619
7620 out->config.rate = out->sample_rate;
7621 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7622 if (is_hdmi) {
7623 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7624 audio_bytes_per_sample(out->format));
7625 }
7626 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007627 }
7628
Derek Chenf6318be2017-06-12 17:16:24 -04007629 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007630 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007631 /* extract car audio stream index */
7632 out->car_audio_stream =
7633 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7634 if (out->car_audio_stream < 0) {
7635 ALOGE("%s: invalid car audio stream %x",
7636 __func__, out->car_audio_stream);
7637 ret = -EINVAL;
7638 goto error_open;
7639 }
Derek Chen5f67a942020-02-24 23:08:13 -08007640 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007641 }
7642
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007643 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007644 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007645 if (!voice_extn_is_compress_voip_supported()) {
7646 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7647 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007648 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7649 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007650 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7651 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007652 out->volume_l = INVALID_OUT_VOLUME;
7653 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007654
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007655 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007656 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007657 uint32_t channel_count =
7658 audio_channel_count_from_out_mask(out->channel_mask);
7659 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7660 out->sample_rate, out->format,
7661 channel_count, false);
7662 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7663 if (frame_size != 0)
7664 out->config.period_size = buffer_size / frame_size;
7665 else
7666 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007667 }
7668 } else {
7669 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7670 voice_extn_compress_voip_is_active(out->dev)) &&
7671 (voice_extn_compress_voip_is_config_supported(config))) {
7672 ret = voice_extn_compress_voip_open_output_stream(out);
7673 if (ret != 0) {
7674 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7675 __func__, ret);
7676 goto error_open;
7677 }
Sujin Panicker19027262019-09-16 18:28:06 +05307678 } else {
7679 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7680 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007681 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007682 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007683 } else if (audio_is_linear_pcm(out->format) &&
7684 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7685 out->channel_mask = config->channel_mask;
7686 out->sample_rate = config->sample_rate;
7687 out->format = config->format;
7688 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7689 // does this change?
7690 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7691 out->config.rate = config->sample_rate;
7692 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7693 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7694 audio_bytes_per_sample(config->format));
7695 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007696 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307697 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307698 pthread_mutex_lock(&adev->lock);
7699 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7700 pthread_mutex_unlock(&adev->lock);
7701
7702 // reject offload during card offline to allow
7703 // fallback to s/w paths
7704 if (offline) {
7705 ret = -ENODEV;
7706 goto error_open;
7707 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007708
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007709 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7710 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7711 ALOGE("%s: Unsupported Offload information", __func__);
7712 ret = -EINVAL;
7713 goto error_open;
7714 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007715
Atul Khare3fa6e542017-08-09 00:56:17 +05307716 if (config->offload_info.format == 0)
7717 config->offload_info.format = config->format;
7718 if (config->offload_info.sample_rate == 0)
7719 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007720
Mingming Yin90310102013-11-13 16:57:00 -08007721 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307722 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007723 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007724 ret = -EINVAL;
7725 goto error_open;
7726 }
7727
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007728 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7729 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7730 (audio_extn_passthru_is_passthrough_stream(out)) &&
7731 !((config->sample_rate == 48000) ||
7732 (config->sample_rate == 96000) ||
7733 (config->sample_rate == 192000))) {
7734 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7735 __func__, config->sample_rate, config->offload_info.format);
7736 ret = -EINVAL;
7737 goto error_open;
7738 }
7739
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007740 out->compr_config.codec = (struct snd_codec *)
7741 calloc(1, sizeof(struct snd_codec));
7742
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007743 if (!out->compr_config.codec) {
7744 ret = -ENOMEM;
7745 goto error_open;
7746 }
7747
Dhananjay Kumarac341582017-02-23 23:42:25 +05307748 out->stream.pause = out_pause;
7749 out->stream.resume = out_resume;
7750 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307751 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307752 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007753 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307754 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007755 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307756 } else {
7757 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7758 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007759 }
vivek mehta446c3962015-09-14 10:57:35 -07007760
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307761 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7762 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007763#ifdef AUDIO_GKI_ENABLED
7764 /* out->compr_config.codec->reserved[1] is for flags */
7765 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7766#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307767 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007768#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307769 }
7770
vivek mehta446c3962015-09-14 10:57:35 -07007771 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007772 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007773 config->format == 0 && config->sample_rate == 0 &&
7774 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007775 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007776 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7777 } else {
7778 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7779 ret = -EEXIST;
7780 goto error_open;
7781 }
vivek mehta446c3962015-09-14 10:57:35 -07007782 }
7783
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007784 if (config->offload_info.channel_mask)
7785 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007786 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007787 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007788 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007789 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307790 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007791 ret = -EINVAL;
7792 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007793 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007794
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007795 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007796 out->sample_rate = config->offload_info.sample_rate;
7797
Mingming Yin3ee55c62014-08-04 14:23:35 -07007798 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007799
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307800 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307801 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307802 audio_extn_dolby_send_ddp_endp_params(adev);
7803 audio_extn_dolby_set_dmid(adev);
7804 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007805
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007806 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007807 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007808 out->compr_config.codec->bit_rate =
7809 config->offload_info.bit_rate;
7810 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307811 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007812 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307813 /* Update bit width only for non passthrough usecases.
7814 * For passthrough usecases, the output will always be opened @16 bit
7815 */
7816 if (!audio_extn_passthru_is_passthrough_stream(out))
7817 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307818
7819 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007820#ifdef AUDIO_GKI_ENABLED
7821 /* out->compr_config.codec->reserved[1] is for flags */
7822 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7823 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7824#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307825 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7826 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007827#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307828
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007829 /*TODO: Do we need to change it for passthrough */
7830 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007831
Manish Dewangana6fc5442015-08-24 20:30:31 +05307832 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7833 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307834 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307835 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307836 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7837 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307838
7839 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7840 AUDIO_FORMAT_PCM) {
7841
7842 /*Based on platform support, configure appropriate alsa format for corresponding
7843 *hal input format.
7844 */
7845 out->compr_config.codec->format = hal_format_to_alsa(
7846 config->offload_info.format);
7847
Ashish Jain83a6cc22016-06-28 14:34:17 +05307848 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307849 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307850 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307851
Dhananjay Kumarac341582017-02-23 23:42:25 +05307852 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307853 *hal input format and alsa format might differ based on platform support.
7854 */
7855 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307856 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307857
7858 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7859
Deeraj Soman93155a62019-09-30 19:00:37 +05307860 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7861 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7862 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7863 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7864 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307865
Ashish Jainf1eaa582016-05-23 20:54:24 +05307866 /* Check if alsa session is configured with the same format as HAL input format,
7867 * if not then derive correct fragment size needed to accomodate the
7868 * conversion of HAL input format to alsa format.
7869 */
7870 audio_extn_utils_update_direct_pcm_fragment_size(out);
7871
7872 /*if hal input and output fragment size is different this indicates HAL input format is
7873 *not same as the alsa format
7874 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307875 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307876 /*Allocate a buffer to convert input data to the alsa configured format.
7877 *size of convert buffer is equal to the size required to hold one fragment size
7878 *worth of pcm data, this is because flinger does not write more than fragment_size
7879 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307880 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7881 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307882 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7883 ret = -ENOMEM;
7884 goto error_open;
7885 }
7886 }
7887 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7888 out->compr_config.fragment_size =
7889 audio_extn_passthru_get_buffer_size(&config->offload_info);
7890 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7891 } else {
7892 out->compr_config.fragment_size =
7893 platform_get_compress_offload_buffer_size(&config->offload_info);
7894 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7895 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007896
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307897 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7898 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7899 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007900 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307901 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007902
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307903 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7904 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7905 }
7906
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007907 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7908 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007909
Manish Dewangan69426c82017-01-30 17:35:36 +05307910 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7911 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7912 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7913 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7914 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7915 } else {
7916 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7917 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007918
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307919 memset(&out->channel_map_param, 0,
7920 sizeof(struct audio_out_channel_map_param));
7921
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007922 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307923 out->send_next_track_params = false;
7924 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007925 out->offload_state = OFFLOAD_STATE_IDLE;
7926 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007927 out->writeAt.tv_sec = 0;
7928 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007929
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007930 audio_extn_dts_create_state_notifier_node(out->usecase);
7931
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007932 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7933 __func__, config->offload_info.version,
7934 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307935
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307936 /* Check if DSD audio format is supported in codec
7937 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307938 */
7939
7940 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307941 (!platform_check_codec_dsd_support(adev->platform) ||
7942 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307943 ret = -EINVAL;
7944 goto error_open;
7945 }
7946
Ashish Jain5106d362016-05-11 19:23:33 +05307947 /* Disable gapless if any of the following is true
7948 * passthrough playback
7949 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307950 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307951 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307952 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307953 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007954 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307955 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307956 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307957 check_and_set_gapless_mode(adev, false);
7958 } else
7959 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007960
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307961 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007962 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7963 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307964 if (config->format == AUDIO_FORMAT_DSD) {
7965 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08007966#ifdef AUDIO_GKI_ENABLED
7967 /* out->compr_config.codec->reserved[0] is for compr_passthr */
7968 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
7969#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307970 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08007971#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307972 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007973
7974 create_offload_callback_thread(out);
7975
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007976 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007977 switch (config->sample_rate) {
7978 case 0:
7979 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7980 break;
7981 case 8000:
7982 case 16000:
7983 case 48000:
7984 out->sample_rate = config->sample_rate;
7985 break;
7986 default:
7987 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7988 config->sample_rate);
7989 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7990 ret = -EINVAL;
7991 goto error_open;
7992 }
7993 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7994 switch (config->channel_mask) {
7995 case AUDIO_CHANNEL_NONE:
7996 case AUDIO_CHANNEL_OUT_STEREO:
7997 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7998 break;
7999 default:
8000 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
8001 config->channel_mask);
8002 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8003 ret = -EINVAL;
8004 goto error_open;
8005 }
8006 switch (config->format) {
8007 case AUDIO_FORMAT_DEFAULT:
8008 case AUDIO_FORMAT_PCM_16_BIT:
8009 out->format = AUDIO_FORMAT_PCM_16_BIT;
8010 break;
8011 default:
8012 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8013 config->format);
8014 config->format = AUDIO_FORMAT_PCM_16_BIT;
8015 ret = -EINVAL;
8016 goto error_open;
8017 }
8018
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308019 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008020 if (ret != 0) {
8021 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008022 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008023 goto error_open;
8024 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008025 } else if (is_single_device_type_equal(&out->device_list,
8026 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008027 switch (config->sample_rate) {
8028 case 0:
8029 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8030 break;
8031 case 8000:
8032 case 16000:
8033 case 48000:
8034 out->sample_rate = config->sample_rate;
8035 break;
8036 default:
8037 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8038 config->sample_rate);
8039 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8040 ret = -EINVAL;
8041 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008042 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008043 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8044 switch (config->channel_mask) {
8045 case AUDIO_CHANNEL_NONE:
8046 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8047 break;
8048 case AUDIO_CHANNEL_OUT_STEREO:
8049 out->channel_mask = config->channel_mask;
8050 break;
8051 default:
8052 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8053 config->channel_mask);
8054 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8055 ret = -EINVAL;
8056 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008057 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008058 switch (config->format) {
8059 case AUDIO_FORMAT_DEFAULT:
8060 out->format = AUDIO_FORMAT_PCM_16_BIT;
8061 break;
8062 case AUDIO_FORMAT_PCM_16_BIT:
8063 out->format = config->format;
8064 break;
8065 default:
8066 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8067 config->format);
8068 config->format = AUDIO_FORMAT_PCM_16_BIT;
8069 ret = -EINVAL;
8070 break;
8071 }
8072 if (ret != 0)
8073 goto error_open;
8074
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008075 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8076 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008077 out->config.rate = out->sample_rate;
8078 out->config.channels =
8079 audio_channel_count_from_out_mask(out->channel_mask);
8080 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008081 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008082 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308083 unsigned int channels = 0;
8084 /*Update config params to default if not set by the caller*/
8085 if (config->sample_rate == 0)
8086 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8087 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8088 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8089 if (config->format == AUDIO_FORMAT_DEFAULT)
8090 config->format = AUDIO_FORMAT_PCM_16_BIT;
8091
8092 channels = audio_channel_count_from_out_mask(out->channel_mask);
8093
Varun Balaraje49253e2017-07-06 19:48:56 +05308094 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8095 out->usecase = get_interactive_usecase(adev);
8096 out->config = pcm_config_low_latency;
8097 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308098 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008099 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8100 out->flags);
8101 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008102 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8103 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8104 out->config = pcm_config_mmap_playback;
8105 out->stream.start = out_start;
8106 out->stream.stop = out_stop;
8107 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8108 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308109 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8110 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008111 out->hal_output_suspend_supported =
8112 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8113 out->dynamic_pm_qos_config_supported =
8114 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8115 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008116 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8117 } else {
8118 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8119 //the mixer path will be a string similar to "low-latency-playback resume"
8120 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8121 strlcat(out->pm_qos_mixer_path,
8122 " resume", MAX_MIXER_PATH_LEN);
8123 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8124 out->pm_qos_mixer_path);
8125 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308126 out->config = pcm_config_low_latency;
8127 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8128 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8129 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308130 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8131 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8132 if (out->config.period_size <= 0) {
8133 ALOGE("Invalid configuration period size is not valid");
8134 ret = -EINVAL;
8135 goto error_open;
8136 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008137 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8138 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8139 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008140 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8141 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8142 out->config = pcm_config_haptics_audio;
8143 if (force_haptic_path)
8144 adev->haptics_config = pcm_config_haptics_audio;
8145 else
8146 adev->haptics_config = pcm_config_haptics;
8147
8148 out->config.channels =
8149 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8150
8151 if (force_haptic_path) {
8152 out->config.channels = 1;
8153 adev->haptics_config.channels = 1;
8154 } else
8155 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 -08008156 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008157 ret = audio_extn_auto_hal_open_output_stream(out);
8158 if (ret) {
8159 ALOGE("%s: Failed to open output stream for bus device", __func__);
8160 ret = -EINVAL;
8161 goto error_open;
8162 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308163 } else {
8164 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008165 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8166 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308167 }
8168 out->hal_ip_format = format = out->format;
8169 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8170 out->hal_op_format = pcm_format_to_hal(out->config.format);
8171 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8172 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008173 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308174 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308175 if (out->hal_ip_format != out->hal_op_format) {
8176 uint32_t buffer_size = out->config.period_size *
8177 format_to_bitwidth_table[out->hal_op_format] *
8178 out->config.channels;
8179 out->convert_buffer = calloc(1, buffer_size);
8180 if (out->convert_buffer == NULL){
8181 ALOGE("Allocation failed for convert buffer for size %d",
8182 out->compr_config.fragment_size);
8183 ret = -ENOMEM;
8184 goto error_open;
8185 }
8186 ALOGD("Convert buffer allocated of size %d", buffer_size);
8187 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008188 }
8189
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008190 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8191 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308192
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008193 /* TODO remove this hardcoding and check why width is zero*/
8194 if (out->bit_width == 0)
8195 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308196 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008197 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008198 &out->device_list, out->flags,
8199 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308200 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308201 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008202 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008203 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8204 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008205 if(adev->primary_output == NULL)
8206 adev->primary_output = out;
8207 else {
8208 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008209 ret = -EEXIST;
8210 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008211 }
8212 }
8213
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008214 /* Check if this usecase is already existing */
8215 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008216 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8217 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008218 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008219 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008220 ret = -EEXIST;
8221 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008222 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008224 pthread_mutex_unlock(&adev->lock);
8225
8226 out->stream.common.get_sample_rate = out_get_sample_rate;
8227 out->stream.common.set_sample_rate = out_set_sample_rate;
8228 out->stream.common.get_buffer_size = out_get_buffer_size;
8229 out->stream.common.get_channels = out_get_channels;
8230 out->stream.common.get_format = out_get_format;
8231 out->stream.common.set_format = out_set_format;
8232 out->stream.common.standby = out_standby;
8233 out->stream.common.dump = out_dump;
8234 out->stream.common.set_parameters = out_set_parameters;
8235 out->stream.common.get_parameters = out_get_parameters;
8236 out->stream.common.add_audio_effect = out_add_audio_effect;
8237 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8238 out->stream.get_latency = out_get_latency;
8239 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008240#ifdef NO_AUDIO_OUT
8241 out->stream.write = out_write_for_no_output;
8242#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008243 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008244#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008245 out->stream.get_render_position = out_get_render_position;
8246 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008247 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008248
Haynes Mathew George16081042017-05-31 17:16:49 -07008249 if (out->realtime)
8250 out->af_period_multiplier = af_period_multiplier;
8251 else
8252 out->af_period_multiplier = 1;
8253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008254 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008255 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008256 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008257
8258 config->format = out->stream.common.get_format(&out->stream.common);
8259 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8260 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308261 register_format(out->format, out->supported_formats);
8262 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8263 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008264
Aalique Grahame22e49102018-12-18 14:23:57 -08008265 out->error_log = error_log_create(
8266 ERROR_LOG_ENTRIES,
8267 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8268
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308269 /*
8270 By locking output stream before registering, we allow the callback
8271 to update stream's state only after stream's initial state is set to
8272 adev state.
8273 */
8274 lock_output_stream(out);
8275 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8276 pthread_mutex_lock(&adev->lock);
8277 out->card_status = adev->card_status;
8278 pthread_mutex_unlock(&adev->lock);
8279 pthread_mutex_unlock(&out->lock);
8280
Aalique Grahame22e49102018-12-18 14:23:57 -08008281 stream_app_type_cfg_init(&out->app_type_cfg);
8282
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008283 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308284 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008285 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008286
8287 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8288 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8289 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008290 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308291 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008292 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008293 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308294 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8295 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008296 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8297 out->usecase, PCM_PLAYBACK);
8298 hdlr_stream_cfg.flags = out->flags;
8299 hdlr_stream_cfg.type = PCM_PLAYBACK;
8300 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8301 &hdlr_stream_cfg);
8302 if (ret) {
8303 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8304 out->adsp_hdlr_stream_handle = NULL;
8305 }
8306 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308307 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8308 is_direct_passthough, false);
8309 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8310 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008311 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008312 if (ret < 0) {
8313 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8314 out->ip_hdlr_handle = NULL;
8315 }
8316 }
Derek Chenf939fb72018-11-13 13:34:41 -08008317
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008318 ret = io_streams_map_insert(adev, &out->stream.common,
8319 out->handle, AUDIO_PATCH_HANDLE_NONE);
8320 if (ret != 0)
8321 goto error_open;
8322
Derek Chenf939fb72018-11-13 13:34:41 -08008323 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8324 calloc(1, sizeof(streams_output_ctxt_t));
8325 if (out_ctxt == NULL) {
8326 ALOGE("%s fail to allocate output ctxt", __func__);
8327 ret = -ENOMEM;
8328 goto error_open;
8329 }
8330 out_ctxt->output = out;
8331
8332 pthread_mutex_lock(&adev->lock);
8333 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8334 pthread_mutex_unlock(&adev->lock);
8335
Eric Laurent994a6932013-07-17 11:51:42 -07008336 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008337 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008338
8339error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308340 if (out->convert_buffer)
8341 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008342 free(out);
8343 *stream_out = NULL;
8344 ALOGD("%s: exit: ret %d", __func__, ret);
8345 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008346}
8347
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308348void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008349 struct audio_stream_out *stream)
8350{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008351 struct stream_out *out = (struct stream_out *)stream;
8352 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008353 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008354
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008355 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308356
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008357 io_streams_map_remove(adev, out->handle);
8358
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308359 // must deregister from sndmonitor first to prevent races
8360 // between the callback and close_stream
8361 audio_extn_snd_mon_unregister_listener(out);
8362
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008363 /* close adsp hdrl session before standby */
8364 if (out->adsp_hdlr_stream_handle) {
8365 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8366 if (ret)
8367 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8368 out->adsp_hdlr_stream_handle = NULL;
8369 }
8370
Manish Dewangan21a850a2017-08-14 12:03:55 +05308371 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008372 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8373 out->ip_hdlr_handle = NULL;
8374 }
8375
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008376 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308377 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008378 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308379 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308380 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008381 if(ret != 0)
8382 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8383 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008384 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008385 out_standby(&stream->common);
8386
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008387 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008388 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008389 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008390 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008391 if (out->compr_config.codec != NULL)
8392 free(out->compr_config.codec);
8393 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008394
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308395 out->a2dp_compress_mute = false;
8396
Varun Balaraje49253e2017-07-06 19:48:56 +05308397 if (is_interactive_usecase(out->usecase))
8398 free_interactive_usecase(adev, out->usecase);
8399
Ashish Jain83a6cc22016-06-28 14:34:17 +05308400 if (out->convert_buffer != NULL) {
8401 free(out->convert_buffer);
8402 out->convert_buffer = NULL;
8403 }
8404
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008405 if (adev->voice_tx_output == out)
8406 adev->voice_tx_output = NULL;
8407
Aalique Grahame22e49102018-12-18 14:23:57 -08008408 error_log_destroy(out->error_log);
8409 out->error_log = NULL;
8410
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308411 if (adev->primary_output == out)
8412 adev->primary_output = NULL;
8413
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008414 pthread_cond_destroy(&out->cond);
8415 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008416
8417 pthread_mutex_lock(&adev->lock);
8418 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8419 if (out_ctxt != NULL) {
8420 list_remove(&out_ctxt->list);
8421 free(out_ctxt);
8422 } else {
8423 ALOGW("%s, output stream already closed", __func__);
8424 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008425 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008426 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008427 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008428}
8429
8430static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8431{
8432 struct audio_device *adev = (struct audio_device *)dev;
8433 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008434 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008435 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008436 int ret;
8437 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008438 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008439 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008440 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008441
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008442 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008443 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008444
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308445 if (!parms)
8446 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308447
Derek Chen6f293672019-04-01 01:40:24 -07008448 /* notify adev and input/output streams on the snd card status */
8449 adev_snd_mon_cb((void *)adev, parms);
8450
8451 list_for_each(node, &adev->active_outputs_list) {
8452 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8453 streams_output_ctxt_t,
8454 list);
8455 out_snd_mon_cb((void *)out_ctxt->output, parms);
8456 }
8457
8458 list_for_each(node, &adev->active_inputs_list) {
8459 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8460 streams_input_ctxt_t,
8461 list);
8462 in_snd_mon_cb((void *)in_ctxt->input, parms);
8463 }
8464
Zhou Songd6d71752019-05-21 18:08:51 +08008465 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308466 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8467 if (ret >= 0) {
8468 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008469 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308470 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008471 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308472 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008473 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008474 }
8475 }
8476
8477 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8478 if (ret>=0) {
8479 if (!strncmp(value, "false", 5) &&
8480 audio_extn_a2dp_source_is_suspended()) {
8481 struct audio_usecase *usecase;
8482 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008483 list_for_each(node, &adev->usecase_list) {
8484 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008485 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008486 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008487 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008488 reassign_device_list(&usecase->stream.in->device_list,
8489 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008490 select_devices(adev, usecase->id);
8491 }
Zhou Songd6d71752019-05-21 18:08:51 +08008492 }
8493 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308494 }
8495
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008496 status = voice_set_parameters(adev, parms);
8497 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008498 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008499
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008500 status = platform_set_parameters(adev->platform, parms);
8501 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008502 goto done;
8503
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008504 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8505 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008506 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008507 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8508 adev->bluetooth_nrec = true;
8509 else
8510 adev->bluetooth_nrec = false;
8511 }
8512
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008513 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8514 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008515 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8516 adev->screen_off = false;
8517 else
8518 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008519 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008520 }
8521
Eric Laurent4b084132018-10-19 17:33:43 -07008522 ret = str_parms_get_int(parms, "rotation", &val);
8523 if (ret >= 0) {
8524 bool reverse_speakers = false;
8525 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8526 switch (val) {
8527 // FIXME: note that the code below assumes that the speakers are in the correct placement
8528 // relative to the user when the device is rotated 90deg from its default rotation. This
8529 // assumption is device-specific, not platform-specific like this code.
8530 case 270:
8531 reverse_speakers = true;
8532 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8533 break;
8534 case 0:
8535 case 180:
8536 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8537 break;
8538 case 90:
8539 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8540 break;
8541 default:
8542 ALOGE("%s: unexpected rotation of %d", __func__, val);
8543 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008544 }
Eric Laurent4b084132018-10-19 17:33:43 -07008545 if (status == 0) {
8546 // check and set swap
8547 // - check if orientation changed and speaker active
8548 // - set rotation and cache the rotation value
8549 adev->camera_orientation =
8550 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8551 if (!audio_extn_is_maxx_audio_enabled())
8552 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8553 }
8554 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008555
Mingming Yin514a8bc2014-07-29 15:22:21 -07008556 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8557 if (ret >= 0) {
8558 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8559 adev->bt_wb_speech_enabled = true;
8560 else
8561 adev->bt_wb_speech_enabled = false;
8562 }
8563
Zhou Song12c29502019-03-16 10:37:18 +08008564 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8565 if (ret >= 0) {
8566 val = atoi(value);
8567 adev->swb_speech_mode = val;
8568 }
8569
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008570 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8571 if (ret >= 0) {
8572 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308573 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008574 if (audio_is_output_device(val) &&
8575 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008576 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008577 platform_get_controller_stream_from_params(parms, &controller, &stream);
8578 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8579 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008580 if (ret < 0) {
8581 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308582 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008583 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008584 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308585 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008586 /*
8587 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8588 * Per AudioPolicyManager, USB device is higher priority than WFD.
8589 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8590 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8591 * starting voice call on USB
8592 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008593 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308594 if (ret >= 0)
8595 audio_extn_usb_add_device(device, atoi(value));
8596
Zhou Song6f862822017-11-06 17:27:57 +08008597 if (!audio_extn_usb_is_tunnel_supported()) {
8598 ALOGV("detected USB connect .. disable proxy");
8599 adev->allow_afe_proxy_usage = false;
8600 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008601 }
8602 }
8603
8604 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8605 if (ret >= 0) {
8606 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308607 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008608 /*
8609 * The HDMI / Displayport disconnect handling has been moved to
8610 * audio extension to ensure that its parameters are not
8611 * invalidated prior to updating sysfs of the disconnect event
8612 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8613 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308614 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008615 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308616 if (ret >= 0)
8617 audio_extn_usb_remove_device(device, atoi(value));
8618
Zhou Song6f862822017-11-06 17:27:57 +08008619 if (!audio_extn_usb_is_tunnel_supported()) {
8620 ALOGV("detected USB disconnect .. enable proxy");
8621 adev->allow_afe_proxy_usage = true;
8622 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008623 }
8624 }
8625
Aalique Grahame22e49102018-12-18 14:23:57 -08008626 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008627 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008628
8629 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008630 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308631 struct audio_usecase *usecase;
8632 struct listnode *node;
8633 list_for_each(node, &adev->usecase_list) {
8634 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308635 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008636 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308637 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008638 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308639 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008640 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308641 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308642 ALOGD("Switching to speaker and muting the stream before select_devices");
8643 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308644 //force device switch to re configure encoder
8645 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308646 ALOGD("Unmuting the stream after select_devices");
8647 usecase->stream.out->a2dp_compress_mute = false;
8648 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 +05308649 audio_extn_a2dp_set_handoff_mode(false);
8650 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308651 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308652 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8653 usecase->stream.out->a2dp_compress_mute) {
8654 pthread_mutex_unlock(&adev->lock);
8655 lock_output_stream(usecase->stream.out);
8656 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008657 reassign_device_list(&usecase->stream.out->device_list,
8658 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308659 check_a2dp_restore_l(adev, usecase->stream.out, true);
8660 pthread_mutex_unlock(&usecase->stream.out->lock);
8661 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308662 }
8663 }
8664 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008665
8666 //handle vr audio setparam
8667 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8668 value, sizeof(value));
8669 if (ret >= 0) {
8670 ALOGI("Setting vr mode to be %s", value);
8671 if (!strncmp(value, "true", 4)) {
8672 adev->vr_audio_mode_enabled = true;
8673 ALOGI("Setting vr mode to true");
8674 } else if (!strncmp(value, "false", 5)) {
8675 adev->vr_audio_mode_enabled = false;
8676 ALOGI("Setting vr mode to false");
8677 } else {
8678 ALOGI("wrong vr mode set");
8679 }
8680 }
8681
Eric Laurent4b084132018-10-19 17:33:43 -07008682 //FIXME: to be replaced by proper video capture properties API
8683 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8684 if (ret >= 0) {
8685 int camera_facing = CAMERA_FACING_BACK;
8686 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8687 camera_facing = CAMERA_FACING_FRONT;
8688 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8689 camera_facing = CAMERA_FACING_BACK;
8690 else {
8691 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8692 goto done;
8693 }
8694 adev->camera_orientation =
8695 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8696 struct audio_usecase *usecase;
8697 struct listnode *node;
8698 list_for_each(node, &adev->usecase_list) {
8699 usecase = node_to_item(node, struct audio_usecase, list);
8700 struct stream_in *in = usecase->stream.in;
8701 if (usecase->type == PCM_CAPTURE && in != NULL &&
8702 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8703 select_devices(adev, in->usecase);
8704 }
8705 }
8706 }
8707
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308708 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008709done:
8710 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008711 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308712error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008713 ALOGV("%s: exit with code(%d)", __func__, status);
8714 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008715}
8716
8717static char* adev_get_parameters(const struct audio_hw_device *dev,
8718 const char *keys)
8719{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308720 ALOGD("%s:%s", __func__, keys);
8721
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008722 struct audio_device *adev = (struct audio_device *)dev;
8723 struct str_parms *reply = str_parms_create();
8724 struct str_parms *query = str_parms_create_str(keys);
8725 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308726 char value[256] = {0};
8727 int ret = 0;
8728
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008729 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008730 if (reply) {
8731 str_parms_destroy(reply);
8732 }
8733 if (query) {
8734 str_parms_destroy(query);
8735 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008736 ALOGE("adev_get_parameters: failed to create query or reply");
8737 return NULL;
8738 }
8739
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008740 //handle vr audio getparam
8741
8742 ret = str_parms_get_str(query,
8743 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8744 value, sizeof(value));
8745
8746 if (ret >= 0) {
8747 bool vr_audio_enabled = false;
8748 pthread_mutex_lock(&adev->lock);
8749 vr_audio_enabled = adev->vr_audio_mode_enabled;
8750 pthread_mutex_unlock(&adev->lock);
8751
8752 ALOGI("getting vr mode to %d", vr_audio_enabled);
8753
8754 if (vr_audio_enabled) {
8755 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8756 "true");
8757 goto exit;
8758 } else {
8759 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8760 "false");
8761 goto exit;
8762 }
8763 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008764
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008765 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008766 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008767 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008768 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008769 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308770 pthread_mutex_unlock(&adev->lock);
8771
Naresh Tannirud7205b62014-06-20 02:54:48 +05308772exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008773 str = str_parms_to_str(reply);
8774 str_parms_destroy(query);
8775 str_parms_destroy(reply);
8776
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308777 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008778 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008779}
8780
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008781static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008782{
8783 return 0;
8784}
8785
8786static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8787{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008788 int ret;
8789 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008790
8791 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8792
Haynes Mathew George5191a852013-09-11 14:19:36 -07008793 pthread_mutex_lock(&adev->lock);
8794 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008795 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008796 pthread_mutex_unlock(&adev->lock);
8797 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008798}
8799
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008800static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8801 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008802{
8803 return -ENOSYS;
8804}
8805
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008806static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8807 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008808{
8809 return -ENOSYS;
8810}
8811
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008812static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8813 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008814{
8815 return -ENOSYS;
8816}
8817
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008818static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8819 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008820{
8821 return -ENOSYS;
8822}
8823
8824static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8825{
8826 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008827 struct listnode *node;
8828 struct audio_usecase *usecase = NULL;
8829 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008831 pthread_mutex_lock(&adev->lock);
8832 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308833 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8834 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008835 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308836 if( mode == AUDIO_MODE_CALL_SCREEN ){
8837 adev->current_call_output = adev->primary_output;
8838 voice_start_call(adev);
8839 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008840 (mode == AUDIO_MODE_NORMAL ||
8841 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008842 list_for_each(node, &adev->usecase_list) {
8843 usecase = node_to_item(node, struct audio_usecase, list);
8844 if (usecase->type == VOICE_CALL)
8845 break;
8846 }
8847 if (usecase &&
8848 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8849 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8850 true);
8851 if (ret != 0) {
8852 /* default service interval was successfully updated,
8853 reopen USB backend with new service interval */
8854 check_usecases_codec_backend(adev,
8855 usecase,
8856 usecase->out_snd_device);
8857 }
8858 }
8859
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008860 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008861 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008862 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008863 // restore device for other active usecases after stop call
8864 list_for_each(node, &adev->usecase_list) {
8865 usecase = node_to_item(node, struct audio_usecase, list);
8866 select_devices(adev, usecase->id);
8867 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008868 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008869 }
8870 pthread_mutex_unlock(&adev->lock);
8871 return 0;
8872}
8873
8874static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8875{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008876 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008877 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008878
8879 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008880 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008881 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008882
Derek Chend2530072014-11-24 12:39:14 -08008883 if (adev->ext_hw_plugin)
8884 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008885
8886 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008887 pthread_mutex_unlock(&adev->lock);
8888
8889 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008890}
8891
8892static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8893{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008894 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008895 return 0;
8896}
8897
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008898static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008899 const struct audio_config *config)
8900{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008901 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008902
Aalique Grahame22e49102018-12-18 14:23:57 -08008903 /* Don't know if USB HIFI in this context so use true to be conservative */
8904 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8905 true /*is_usb_hifi */) != 0)
8906 return 0;
8907
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008908 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8909 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008910}
8911
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008912static bool adev_input_allow_hifi_record(struct audio_device *adev,
8913 audio_devices_t devices,
8914 audio_input_flags_t flags,
8915 audio_source_t source) {
8916 const bool allowed = true;
8917
8918 if (!audio_is_usb_in_device(devices))
8919 return !allowed;
8920
8921 switch (flags) {
8922 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008923 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008924 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8925 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008926 default:
8927 return !allowed;
8928 }
8929
8930 switch (source) {
8931 case AUDIO_SOURCE_DEFAULT:
8932 case AUDIO_SOURCE_MIC:
8933 case AUDIO_SOURCE_UNPROCESSED:
8934 break;
8935 default:
8936 return !allowed;
8937 }
8938
8939 switch (adev->mode) {
8940 case 0:
8941 break;
8942 default:
8943 return !allowed;
8944 }
8945
8946 return allowed;
8947}
8948
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008949static int adev_update_voice_comm_input_stream(struct stream_in *in,
8950 struct audio_config *config)
8951{
8952 bool valid_rate = (config->sample_rate == 8000 ||
8953 config->sample_rate == 16000 ||
8954 config->sample_rate == 32000 ||
8955 config->sample_rate == 48000);
8956 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8957
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008958 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008959 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008960 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8961 in->config = default_pcm_config_voip_copp;
8962 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8963 DEFAULT_VOIP_BUF_DURATION_MS,
8964 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008965 } else {
8966 ALOGW("%s No valid input in voip, use defaults"
8967 "sample rate %u, channel mask 0x%X",
8968 __func__, config->sample_rate, in->channel_mask);
8969 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008970 in->config.rate = config->sample_rate;
8971 in->sample_rate = config->sample_rate;
8972 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008973 //XXX needed for voice_extn_compress_voip_open_input_stream
8974 in->config.rate = config->sample_rate;
8975 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05308976 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008977 voice_extn_compress_voip_is_active(in->dev)) &&
8978 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8979 valid_rate && valid_ch) {
8980 voice_extn_compress_voip_open_input_stream(in);
8981 // update rate entries to match config from AF
8982 in->config.rate = config->sample_rate;
8983 in->sample_rate = config->sample_rate;
8984 } else {
8985 ALOGW("%s compress voip not active, use defaults", __func__);
8986 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008987 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008988 return 0;
8989}
8990
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008991static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008992 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008993 audio_devices_t devices,
8994 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008995 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308996 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008997 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008998 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008999{
9000 struct audio_device *adev = (struct audio_device *)dev;
9001 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009002 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07009003 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009004 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05309005 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009006 bool is_usb_dev = audio_is_usb_in_device(devices);
9007 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
9008 devices,
9009 flags,
9010 source);
Andy Hung94320602018-10-29 18:31:12 -07009011 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9012 " sample_rate %u, channel_mask %#x, format %#x",
9013 __func__, flags, is_usb_dev, may_use_hifi_record,
9014 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309015
kunleizdff872d2018-08-20 14:40:33 +08009016 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009017 is_usb_dev = false;
9018 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9019 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9020 __func__, devices);
9021 }
9022
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009023 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009024
9025 if (!(is_usb_dev && may_use_hifi_record)) {
9026 if (config->sample_rate == 0)
9027 config->sample_rate = 48000;
9028 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9029 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9030 if (config->format == AUDIO_FORMAT_DEFAULT)
9031 config->format = AUDIO_FORMAT_PCM_16_BIT;
9032
9033 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9034
Aalique Grahame22e49102018-12-18 14:23:57 -08009035 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9036 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009037 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309038 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009039
Rahul Sharma99770982019-03-06 17:05:26 +05309040 pthread_mutex_lock(&adev->lock);
9041 if (in_get_stream(adev, handle) != NULL) {
9042 ALOGW("%s, input stream already opened", __func__);
9043 ret = -EEXIST;
9044 }
9045 pthread_mutex_unlock(&adev->lock);
9046 if (ret)
9047 return ret;
9048
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009049 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009050
9051 if (!in) {
9052 ALOGE("failed to allocate input stream");
9053 return -ENOMEM;
9054 }
9055
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309056 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309057 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9058 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009059 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009060 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009061
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009062 in->stream.common.get_sample_rate = in_get_sample_rate;
9063 in->stream.common.set_sample_rate = in_set_sample_rate;
9064 in->stream.common.get_buffer_size = in_get_buffer_size;
9065 in->stream.common.get_channels = in_get_channels;
9066 in->stream.common.get_format = in_get_format;
9067 in->stream.common.set_format = in_set_format;
9068 in->stream.common.standby = in_standby;
9069 in->stream.common.dump = in_dump;
9070 in->stream.common.set_parameters = in_set_parameters;
9071 in->stream.common.get_parameters = in_get_parameters;
9072 in->stream.common.add_audio_effect = in_add_audio_effect;
9073 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9074 in->stream.set_gain = in_set_gain;
9075 in->stream.read = in_read;
9076 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009077 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309078 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009079 in->stream.set_microphone_direction = in_set_microphone_direction;
9080 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009081 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009082
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009083 list_init(&in->device_list);
9084 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009085 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009086 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009087 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009088 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009089 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009090 in->bit_width = 16;
9091 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009092 in->direction = MIC_DIRECTION_UNSPECIFIED;
9093 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009094 list_init(&in->aec_list);
9095 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009096 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009097
Andy Hung94320602018-10-29 18:31:12 -07009098 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009099 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9100 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9101 /* Force channel config requested to mono if incall
9102 record is being requested for only uplink/downlink */
9103 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9104 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9105 ret = -EINVAL;
9106 goto err_open;
9107 }
9108 }
9109
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009110 if (is_usb_dev && may_use_hifi_record) {
9111 /* HiFi record selects an appropriate format, channel, rate combo
9112 depending on sink capabilities*/
9113 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9114 &config->format,
9115 &in->supported_formats[0],
9116 MAX_SUPPORTED_FORMATS,
9117 &config->channel_mask,
9118 &in->supported_channel_masks[0],
9119 MAX_SUPPORTED_CHANNEL_MASKS,
9120 &config->sample_rate,
9121 &in->supported_sample_rates[0],
9122 MAX_SUPPORTED_SAMPLE_RATES);
9123 if (ret != 0) {
9124 ret = -EINVAL;
9125 goto err_open;
9126 }
9127 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009128 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309129 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309130 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9131 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9132 in->config.format = PCM_FORMAT_S32_LE;
9133 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309134 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9135 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9136 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9137 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9138 bool ret_error = false;
9139 in->bit_width = 24;
9140 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9141 from HAL is 24_packed and 8_24
9142 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9143 24_packed return error indicating supported format is 24_packed
9144 *> In case of any other source requesting 24 bit or float return error
9145 indicating format supported is 16 bit only.
9146
9147 on error flinger will retry with supported format passed
9148 */
9149 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9150 (source != AUDIO_SOURCE_CAMCORDER)) {
9151 config->format = AUDIO_FORMAT_PCM_16_BIT;
9152 if (config->sample_rate > 48000)
9153 config->sample_rate = 48000;
9154 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009155 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9156 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309157 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9158 ret_error = true;
9159 }
9160
9161 if (ret_error) {
9162 ret = -EINVAL;
9163 goto err_open;
9164 }
9165 }
9166
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009167 in->channel_mask = config->channel_mask;
9168 in->format = config->format;
9169
9170 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309171
9172 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9173 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9174 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9175 else {
9176 ret = -EINVAL;
9177 goto err_open;
9178 }
9179 }
9180
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009181 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309182 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9183 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009184 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9185 is_low_latency = true;
9186#if LOW_LATENCY_CAPTURE_USE_CASE
9187 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9188#endif
9189 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009190 if (!in->realtime) {
9191 in->config = pcm_config_audio_capture;
9192 frame_size = audio_stream_in_frame_size(&in->stream);
9193 buffer_size = get_input_buffer_size(config->sample_rate,
9194 config->format,
9195 channel_count,
9196 is_low_latency);
9197 in->config.period_size = buffer_size / frame_size;
9198 in->config.rate = config->sample_rate;
9199 in->af_period_multiplier = 1;
9200 } else {
9201 // period size is left untouched for rt mode playback
9202 in->config = pcm_config_audio_capture_rt;
9203 in->af_period_multiplier = af_period_multiplier;
9204 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009205 }
9206
9207 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9208 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9209 in->realtime = 0;
9210 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9211 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009212 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009213 in->stream.start = in_start;
9214 in->stream.stop = in_stop;
9215 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9216 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009217 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
Haynes Mathew George46740472017-10-27 18:40:12 -07009218 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009219 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9220 in->config = pcm_config_audio_capture;
9221 frame_size = audio_stream_in_frame_size(&in->stream);
9222 buffer_size = get_input_buffer_size(config->sample_rate,
9223 config->format,
9224 channel_count,
9225 false /*is_low_latency*/);
9226 in->config.period_size = buffer_size / frame_size;
9227 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009228 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009229 switch (config->format) {
9230 case AUDIO_FORMAT_PCM_32_BIT:
9231 in->bit_width = 32;
9232 break;
9233 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9234 case AUDIO_FORMAT_PCM_8_24_BIT:
9235 in->bit_width = 24;
9236 break;
9237 default:
9238 in->bit_width = 16;
9239 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009240 } else if (is_single_device_type_equal(&in->device_list,
9241 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9242 is_single_device_type_equal(&in->device_list,
9243 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009244 if (config->sample_rate == 0)
9245 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9246 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9247 config->sample_rate != 8000) {
9248 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9249 ret = -EINVAL;
9250 goto err_open;
9251 }
9252 if (config->format == AUDIO_FORMAT_DEFAULT)
9253 config->format = AUDIO_FORMAT_PCM_16_BIT;
9254 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9255 config->format = AUDIO_FORMAT_PCM_16_BIT;
9256 ret = -EINVAL;
9257 goto err_open;
9258 }
9259
9260 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9261 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009262 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009263 in->af_period_multiplier = 1;
9264 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9265 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9266 (config->sample_rate == 8000 ||
9267 config->sample_rate == 16000 ||
9268 config->sample_rate == 32000 ||
9269 config->sample_rate == 48000) &&
9270 channel_count == 1) {
9271 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9272 in->config = pcm_config_audio_capture;
9273 frame_size = audio_stream_in_frame_size(&in->stream);
9274 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9275 config->sample_rate,
9276 config->format,
9277 channel_count, false /*is_low_latency*/);
9278 in->config.period_size = buffer_size / frame_size;
9279 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9280 in->config.rate = config->sample_rate;
9281 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009282 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309283 int ret_val;
9284 pthread_mutex_lock(&adev->lock);
9285 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9286 in, config, &channel_mask_updated);
9287 pthread_mutex_unlock(&adev->lock);
9288
9289 if (!ret_val) {
9290 if (channel_mask_updated == true) {
9291 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9292 __func__, config->channel_mask);
9293 ret = -EINVAL;
9294 goto err_open;
9295 }
9296 ALOGD("%s: created multi-channel session succesfully",__func__);
9297 } else if (audio_extn_compr_cap_enabled() &&
9298 audio_extn_compr_cap_format_supported(config->format) &&
9299 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9300 audio_extn_compr_cap_init(in);
9301 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309302 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309303 if (ret)
9304 goto err_open;
9305 } else {
9306 in->config = pcm_config_audio_capture;
9307 in->config.rate = config->sample_rate;
9308 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309309 in->format = config->format;
9310 frame_size = audio_stream_in_frame_size(&in->stream);
9311 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009312 config->format,
9313 channel_count,
9314 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009315 /* prevent division-by-zero */
9316 if (frame_size == 0) {
9317 ALOGE("%s: Error frame_size==0", __func__);
9318 ret = -EINVAL;
9319 goto err_open;
9320 }
9321
Revathi Uddarajud2634032017-12-07 14:42:34 +05309322 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009323 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009324
Revathi Uddarajud2634032017-12-07 14:42:34 +05309325 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9326 /* optionally use VOIP usecase depending on config(s) */
9327 ret = adev_update_voice_comm_input_stream(in, config);
9328 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009329
Revathi Uddarajud2634032017-12-07 14:42:34 +05309330 if (ret) {
9331 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9332 goto err_open;
9333 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009334 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309335
9336 /* assign concurrent capture usecase if record has to caried out from
9337 * actual hardware input source */
9338 if (audio_extn_is_concurrent_capture_enabled() &&
9339 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309340 /* Acquire lock to avoid two concurrent use cases initialized to
9341 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009342
Samyak Jainc37062f2019-04-25 18:41:06 +05309343 if (in->usecase == USECASE_AUDIO_RECORD) {
9344 pthread_mutex_lock(&adev->lock);
9345 if (!(adev->pcm_record_uc_state)) {
9346 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9347 adev->pcm_record_uc_state = 1;
9348 pthread_mutex_unlock(&adev->lock);
9349 } else {
9350 pthread_mutex_unlock(&adev->lock);
9351 /* Assign compress record use case for second record */
9352 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9353 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9354 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9355 if (audio_extn_cin_applicable_stream(in)) {
9356 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309357 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309358 if (ret)
9359 goto err_open;
9360 }
9361 }
9362 }
kunleiz28c73e72019-03-27 17:24:04 +08009363 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009364 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309365 if (audio_extn_ssr_get_stream() != in)
9366 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009367
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009368 in->sample_rate = in->config.rate;
9369
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309370 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9371 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009372 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009373 in->sample_rate, in->bit_width,
9374 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309375 register_format(in->format, in->supported_formats);
9376 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9377 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309378
Aalique Grahame22e49102018-12-18 14:23:57 -08009379 in->error_log = error_log_create(
9380 ERROR_LOG_ENTRIES,
9381 1000000000 /* aggregate consecutive identical errors within one second */);
9382
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009383 /* This stream could be for sound trigger lab,
9384 get sound trigger pcm if present */
9385 audio_extn_sound_trigger_check_and_get_session(in);
9386
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309387 lock_input_stream(in);
9388 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9389 pthread_mutex_lock(&adev->lock);
9390 in->card_status = adev->card_status;
9391 pthread_mutex_unlock(&adev->lock);
9392 pthread_mutex_unlock(&in->lock);
9393
Aalique Grahame22e49102018-12-18 14:23:57 -08009394 stream_app_type_cfg_init(&in->app_type_cfg);
9395
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009396 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009397
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009398 ret = io_streams_map_insert(adev, &in->stream.common,
9399 handle, AUDIO_PATCH_HANDLE_NONE);
9400 if (ret != 0)
9401 goto err_open;
9402
Derek Chenf939fb72018-11-13 13:34:41 -08009403 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9404 calloc(1, sizeof(streams_input_ctxt_t));
9405 if (in_ctxt == NULL) {
9406 ALOGE("%s fail to allocate input ctxt", __func__);
9407 ret = -ENOMEM;
9408 goto err_open;
9409 }
9410 in_ctxt->input = in;
9411
9412 pthread_mutex_lock(&adev->lock);
9413 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9414 pthread_mutex_unlock(&adev->lock);
9415
Eric Laurent994a6932013-07-17 11:51:42 -07009416 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009417 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009418
9419err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309420 if (in->usecase == USECASE_AUDIO_RECORD) {
9421 pthread_mutex_lock(&adev->lock);
9422 adev->pcm_record_uc_state = 0;
9423 pthread_mutex_unlock(&adev->lock);
9424 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009425 free(in);
9426 *stream_in = NULL;
9427 return ret;
9428}
9429
9430static void adev_close_input_stream(struct audio_hw_device *dev,
9431 struct audio_stream_in *stream)
9432{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009433 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009434 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009435 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309436
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309437 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009438
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009439 if (in == NULL) {
9440 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9441 return;
9442 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009443 io_streams_map_remove(adev, in->capture_handle);
9444
kunleiz70e57612018-12-28 17:50:23 +08009445 /* must deregister from sndmonitor first to prevent races
9446 * between the callback and close_stream
9447 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309448 audio_extn_snd_mon_unregister_listener(stream);
9449
kunleiz70e57612018-12-28 17:50:23 +08009450 /* Disable echo reference if there are no active input, hfp call
9451 * and sound trigger while closing input stream
9452 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009453 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009454 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009455 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9456 struct listnode out_devices;
9457 list_init(&out_devices);
9458 platform_set_echo_reference(adev, false, &out_devices);
9459 } else
kunleiz70e57612018-12-28 17:50:23 +08009460 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309461
Weiyin Jiang2995f662019-04-17 14:25:12 +08009462 error_log_destroy(in->error_log);
9463 in->error_log = NULL;
9464
Pallavid7c7a272018-01-16 11:22:55 +05309465
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009466 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309467 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009468 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309469 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009470 if (ret != 0)
9471 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9472 __func__, ret);
9473 } else
9474 in_standby(&stream->common);
9475
Revathi Uddarajud2634032017-12-07 14:42:34 +05309476 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309477 if (in->usecase == USECASE_AUDIO_RECORD) {
9478 adev->pcm_record_uc_state = 0;
9479 }
9480
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009481 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9482 adev->enable_voicerx = false;
9483 }
9484
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009485 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009486 audio_extn_ssr_deinit();
9487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009488
Garmond Leunge2433c32017-09-28 21:51:22 -07009489 if (audio_extn_ffv_get_stream() == in) {
9490 audio_extn_ffv_stream_deinit();
9491 }
9492
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309493 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009494 audio_extn_compr_cap_format_supported(in->config.format))
9495 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309496
Dhananjay Kumar7dbe3562019-08-30 05:49:33 +05309497 if (audio_extn_cin_attached_usecase(in))
Manish Dewangan46e07982018-12-13 18:18:59 +05309498 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009499
Mingming Yinfd7607b2016-01-22 12:48:44 -08009500 if (in->is_st_session) {
9501 ALOGV("%s: sound trigger pcm stop lab", __func__);
9502 audio_extn_sound_trigger_stop_lab(in);
9503 }
Derek Chenf939fb72018-11-13 13:34:41 -08009504 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9505 if (in_ctxt != NULL) {
9506 list_remove(&in_ctxt->list);
9507 free(in_ctxt);
9508 } else {
9509 ALOGW("%s, input stream already closed", __func__);
9510 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009511 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309512 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009513 return;
9514}
9515
Aalique Grahame22e49102018-12-18 14:23:57 -08009516/* verifies input and output devices and their capabilities.
9517 *
9518 * This verification is required when enabling extended bit-depth or
9519 * sampling rates, as not all qcom products support it.
9520 *
9521 * Suitable for calling only on initialization such as adev_open().
9522 * It fills the audio_device use_case_table[] array.
9523 *
9524 * Has a side-effect that it needs to configure audio routing / devices
9525 * in order to power up the devices and read the device parameters.
9526 * It does not acquire any hw device lock. Should restore the devices
9527 * back to "normal state" upon completion.
9528 */
9529static int adev_verify_devices(struct audio_device *adev)
9530{
9531 /* enumeration is a bit difficult because one really wants to pull
9532 * the use_case, device id, etc from the hidden pcm_device_table[].
9533 * In this case there are the following use cases and device ids.
9534 *
9535 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9536 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9537 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9538 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9539 * [USECASE_AUDIO_RECORD] = {0, 0},
9540 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9541 * [USECASE_VOICE_CALL] = {2, 2},
9542 *
9543 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9544 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9545 */
9546
9547 /* should be the usecases enabled in adev_open_input_stream() */
9548 static const int test_in_usecases[] = {
9549 USECASE_AUDIO_RECORD,
9550 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9551 };
9552 /* should be the usecases enabled in adev_open_output_stream()*/
9553 static const int test_out_usecases[] = {
9554 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9555 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9556 };
9557 static const usecase_type_t usecase_type_by_dir[] = {
9558 PCM_PLAYBACK,
9559 PCM_CAPTURE,
9560 };
9561 static const unsigned flags_by_dir[] = {
9562 PCM_OUT,
9563 PCM_IN,
9564 };
9565
9566 size_t i;
9567 unsigned dir;
9568 const unsigned card_id = adev->snd_card;
9569
9570 for (dir = 0; dir < 2; ++dir) {
9571 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9572 const unsigned flags_dir = flags_by_dir[dir];
9573 const size_t testsize =
9574 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9575 const int *testcases =
9576 dir ? test_in_usecases : test_out_usecases;
9577 const audio_devices_t audio_device =
9578 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9579
9580 for (i = 0; i < testsize; ++i) {
9581 const audio_usecase_t audio_usecase = testcases[i];
9582 int device_id;
9583 struct pcm_params **pparams;
9584 struct stream_out out;
9585 struct stream_in in;
9586 struct audio_usecase uc_info;
9587 int retval;
9588
9589 pparams = &adev->use_case_table[audio_usecase];
9590 pcm_params_free(*pparams); /* can accept null input */
9591 *pparams = NULL;
9592
9593 /* find the device ID for the use case (signed, for error) */
9594 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9595 if (device_id < 0)
9596 continue;
9597
9598 /* prepare structures for device probing */
9599 memset(&uc_info, 0, sizeof(uc_info));
9600 uc_info.id = audio_usecase;
9601 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009602 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009603 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009604 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009605 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009606 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009607 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9608 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009609 }
9610 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009611 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009612 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009613 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009614 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009615 uc_info.in_snd_device = SND_DEVICE_NONE;
9616 uc_info.out_snd_device = SND_DEVICE_NONE;
9617 list_add_tail(&adev->usecase_list, &uc_info.list);
9618
9619 /* select device - similar to start_(in/out)put_stream() */
9620 retval = select_devices(adev, audio_usecase);
9621 if (retval >= 0) {
9622 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9623#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009624 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009625 if (*pparams) {
9626 ALOGV("%s: (%s) card %d device %d", __func__,
9627 dir ? "input" : "output", card_id, device_id);
9628 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9629 } else {
9630 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9631 }
9632#endif
9633 }
9634
9635 /* deselect device - similar to stop_(in/out)put_stream() */
9636 /* 1. Get and set stream specific mixer controls */
9637 retval = disable_audio_route(adev, &uc_info);
9638 /* 2. Disable the rx device */
9639 retval = disable_snd_device(adev,
9640 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9641 list_remove(&uc_info.list);
9642 }
9643 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009644 return 0;
9645}
9646
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009647int update_patch(unsigned int num_sources,
9648 const struct audio_port_config *sources,
9649 unsigned int num_sinks,
9650 const struct audio_port_config *sinks,
9651 audio_patch_handle_t handle,
9652 struct audio_patch_info *p_info,
9653 patch_type_t patch_type, bool new_patch)
9654{
9655 ALOGD("%s: enter", __func__);
9656
9657 if (p_info == NULL) {
9658 ALOGE("%s: Invalid patch pointer", __func__);
9659 return -EINVAL;
9660 }
9661
9662 if (new_patch) {
9663 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9664 if (p_info->patch == NULL) {
9665 ALOGE("%s: Could not allocate patch", __func__);
9666 return -ENOMEM;
9667 }
9668 }
9669
9670 p_info->patch->id = handle;
9671 p_info->patch->num_sources = num_sources;
9672 p_info->patch->num_sinks = num_sinks;
9673
9674 for (int i = 0; i < num_sources; i++)
9675 p_info->patch->sources[i] = sources[i];
9676 for (int i = 0; i < num_sinks; i++)
9677 p_info->patch->sinks[i] = sinks[i];
9678
9679 p_info->patch_type = patch_type;
9680 return 0;
9681}
9682
9683audio_patch_handle_t generate_patch_handle()
9684{
9685 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9686 if (++patch_handle < 0)
9687 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9688 return patch_handle;
9689}
9690
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309691int adev_create_audio_patch(struct audio_hw_device *dev,
9692 unsigned int num_sources,
9693 const struct audio_port_config *sources,
9694 unsigned int num_sinks,
9695 const struct audio_port_config *sinks,
9696 audio_patch_handle_t *handle)
9697{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009698 int ret = 0;
9699 struct audio_device *adev = (struct audio_device *)dev;
9700 struct audio_patch_info *p_info = NULL;
9701 patch_type_t patch_type = PATCH_NONE;
9702 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9703 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9704 struct audio_stream_info *s_info = NULL;
9705 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009706 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009707 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9708 bool new_patch = false;
9709 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309710
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009711 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9712 num_sources, num_sinks, *handle);
9713
9714 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9715 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9716 ALOGE("%s: Invalid patch arguments", __func__);
9717 ret = -EINVAL;
9718 goto done;
9719 }
9720
9721 if (num_sources > 1) {
9722 ALOGE("%s: Multiple sources are not supported", __func__);
9723 ret = -EINVAL;
9724 goto done;
9725 }
9726
9727 if (sources == NULL || sinks == NULL) {
9728 ALOGE("%s: Invalid sources or sinks port config", __func__);
9729 ret = -EINVAL;
9730 goto done;
9731 }
9732
9733 ALOGV("%s: source role %d, source type %d", __func__,
9734 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009735 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009736
9737 // Populate source/sink information and fetch stream info
9738 switch (sources[0].type) {
9739 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9740 device_type = sources[0].ext.device.type;
9741 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009742 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009743 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9744 patch_type = PATCH_CAPTURE;
9745 io_handle = sinks[0].ext.mix.handle;
9746 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009747 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009748 __func__, device_type, io_handle);
9749 } else {
9750 // Device to device patch is not implemented.
9751 // This space will need changes if audio HAL
9752 // handles device to device patches in the future.
9753 patch_type = PATCH_DEVICE_LOOPBACK;
9754 }
9755 break;
9756 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9757 io_handle = sources[0].ext.mix.handle;
9758 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009759 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009760 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009761 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009762 }
9763 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009764 ALOGD("%s: Playback patch from mix handle %d to device %x",
9765 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009766 break;
9767 case AUDIO_PORT_TYPE_SESSION:
9768 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009769 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9770 ret = -EINVAL;
9771 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009772 }
9773
9774 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009775
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009776 // Generate patch info and update patch
9777 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009778 *handle = generate_patch_handle();
9779 p_info = (struct audio_patch_info *)
9780 calloc(1, sizeof(struct audio_patch_info));
9781 if (p_info == NULL) {
9782 ALOGE("%s: Failed to allocate memory", __func__);
9783 pthread_mutex_unlock(&adev->lock);
9784 ret = -ENOMEM;
9785 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009786 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009787 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009788 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009789 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009790 if (p_info == NULL) {
9791 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9792 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009793 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009794 ret = -EINVAL;
9795 goto done;
9796 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009797 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009798 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009799 *handle, p_info, patch_type, new_patch);
9800
9801 // Fetch stream info of associated mix for playback or capture patches
9802 if (p_info->patch_type == PATCH_PLAYBACK ||
9803 p_info->patch_type == PATCH_CAPTURE) {
9804 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9805 if (s_info == NULL) {
9806 ALOGE("%s: Failed to obtain stream info", __func__);
9807 if (new_patch)
9808 free(p_info);
9809 pthread_mutex_unlock(&adev->lock);
9810 ret = -EINVAL;
9811 goto done;
9812 }
9813 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9814 s_info->patch_handle = *handle;
9815 stream = s_info->stream;
9816 }
9817 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009818
9819 // Update routing for stream
9820 if (stream != NULL) {
9821 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009822 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009823 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009824 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009825 if (ret < 0) {
9826 pthread_mutex_lock(&adev->lock);
9827 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9828 if (new_patch)
9829 free(p_info);
9830 pthread_mutex_unlock(&adev->lock);
9831 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9832 goto done;
9833 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009834 }
9835
9836 // Add new patch to patch map
9837 if (!ret && new_patch) {
9838 pthread_mutex_lock(&adev->lock);
9839 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009840 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009841 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009842 }
9843
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009844done:
9845 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009846 num_sources,
9847 sources,
9848 num_sinks,
9849 sinks,
9850 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009851 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009852 num_sources,
9853 sources,
9854 num_sinks,
9855 sinks,
9856 handle);
9857 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309858}
9859
9860int adev_release_audio_patch(struct audio_hw_device *dev,
9861 audio_patch_handle_t handle)
9862{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009863 struct audio_device *adev = (struct audio_device *) dev;
9864 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009865 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009866 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009867
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009868 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9869 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9870 ret = -EINVAL;
9871 goto done;
9872 }
9873
9874 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009875 pthread_mutex_lock(&adev->lock);
9876 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009877 if (p_info == NULL) {
9878 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009879 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009880 ret = -EINVAL;
9881 goto done;
9882 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009883 struct audio_patch *patch = p_info->patch;
9884 if (patch == NULL) {
9885 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009886 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009887 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009888 goto done;
9889 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009890 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9891 switch (patch->sources[0].type) {
9892 case AUDIO_PORT_TYPE_MIX:
9893 io_handle = patch->sources[0].ext.mix.handle;
9894 break;
9895 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009896 if (p_info->patch_type == PATCH_CAPTURE)
9897 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009898 break;
9899 case AUDIO_PORT_TYPE_SESSION:
9900 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009901 pthread_mutex_unlock(&adev->lock);
9902 ret = -EINVAL;
9903 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009904 }
9905
9906 // Remove patch and reset patch handle in stream info
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009907 patch_type_t patch_type = p_info->patch_type;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009908 patch_map_remove_l(adev, handle);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009909 if (patch_type == PATCH_PLAYBACK ||
9910 patch_type == PATCH_CAPTURE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009911 struct audio_stream_info *s_info =
9912 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9913 if (s_info == NULL) {
9914 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
9915 pthread_mutex_unlock(&adev->lock);
9916 goto done;
9917 }
9918 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9919 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009920 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009921 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009922
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009923 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009924 struct listnode devices;
9925 list_init(&devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009926 if (patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009927 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Latace2b9fa2020-03-10 15:04:15 -07009928 else if (patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009929 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009930 }
9931
9932 if (ret < 0)
9933 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9934
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009935done:
9936 audio_extn_hw_loopback_release_audio_patch(dev, handle);
9937 audio_extn_auto_hal_release_audio_patch(dev, handle);
9938
9939 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -08009940 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309941}
9942
9943int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9944{
Derek Chenf13dd492018-11-13 14:53:51 -08009945 int ret = 0;
9946
9947 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9948 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9949 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309950}
9951
9952int adev_set_audio_port_config(struct audio_hw_device *dev,
9953 const struct audio_port_config *config)
9954{
Derek Chenf13dd492018-11-13 14:53:51 -08009955 int ret = 0;
9956
9957 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9958 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9959 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309960}
9961
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009962static int adev_dump(const audio_hw_device_t *device __unused,
9963 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009964{
9965 return 0;
9966}
9967
9968static int adev_close(hw_device_t *device)
9969{
Aalique Grahame22e49102018-12-18 14:23:57 -08009970 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309971 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009972
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309973 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009974 return 0;
9975
9976 pthread_mutex_lock(&adev_init_lock);
9977
9978 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309979 if (audio_extn_spkr_prot_is_enabled())
9980 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +05309981 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309982 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009983 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009984 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009985 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009986 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309987 audio_extn_utils_release_streams_cfg_lists(
9988 &adev->streams_output_cfg_list,
9989 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309990 if (audio_extn_qap_is_enabled())
9991 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309992 if (audio_extn_qaf_is_enabled())
9993 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009994 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009995 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009996 free(adev->snd_dev_ref_cnt);
9997 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009998 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9999 pcm_params_free(adev->use_case_table[i]);
10000 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010001 if (adev->adm_deinit)
10002 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010003 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010004 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010005 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010006 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010007 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010008 if (adev->device_cfg_params) {
10009 free(adev->device_cfg_params);
10010 adev->device_cfg_params = NULL;
10011 }
Derek Chend2530072014-11-24 12:39:14 -080010012 if(adev->ext_hw_plugin)
10013 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010014 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010015 free_map(adev->patch_map);
10016 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010017 free(device);
10018 adev = NULL;
10019 }
10020 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010021 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010022 return 0;
10023}
10024
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010025/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10026 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10027 * just that it _might_ work.
10028 */
10029static int period_size_is_plausible_for_low_latency(int period_size)
10030{
10031 switch (period_size) {
10032 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010033 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010034 case 240:
10035 case 320:
10036 case 480:
10037 return 1;
10038 default:
10039 return 0;
10040 }
10041}
10042
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010043static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10044{
10045 bool is_snd_card_status = false;
10046 bool is_ext_device_status = false;
10047 char value[32];
10048 int card = -1;
10049 card_status_t status;
10050
10051 if (cookie != adev || !parms)
10052 return;
10053
10054 if (!parse_snd_card_status(parms, &card, &status)) {
10055 is_snd_card_status = true;
10056 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10057 is_ext_device_status = true;
10058 } else {
10059 // not a valid event
10060 return;
10061 }
10062
10063 pthread_mutex_lock(&adev->lock);
10064 if (card == adev->snd_card || is_ext_device_status) {
10065 if (is_snd_card_status && adev->card_status != status) {
10066 adev->card_status = status;
10067 platform_snd_card_update(adev->platform, status);
10068 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010069 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010070 if (status == CARD_STATUS_OFFLINE)
10071 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010072 } else if (is_ext_device_status) {
10073 platform_set_parameters(adev->platform, parms);
10074 }
10075 }
10076 pthread_mutex_unlock(&adev->lock);
10077 return;
10078}
10079
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010080/* out and adev lock held */
10081static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10082{
10083 struct audio_usecase *uc_info;
10084 float left_p;
10085 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010086 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010087
10088 uc_info = get_usecase_from_list(adev, out->usecase);
10089 if (uc_info == NULL) {
10090 ALOGE("%s: Could not find the usecase (%d) in the list",
10091 __func__, out->usecase);
10092 return -EINVAL;
10093 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010094 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010095
10096 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10097 out->usecase, use_case_table[out->usecase]);
10098
10099 if (restore) {
10100 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010101 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010102 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010103 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10104 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010105 pthread_mutex_lock(&out->compr_mute_lock);
10106 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010107 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010108 out->a2dp_compress_mute = false;
10109 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10110 }
10111 pthread_mutex_unlock(&out->compr_mute_lock);
10112 }
10113 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010114 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10115 // mute compress stream if suspended
10116 pthread_mutex_lock(&out->compr_mute_lock);
10117 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010118 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010119 assign_devices(&devices, &out->device_list);
10120 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010121 left_p = out->volume_l;
10122 right_p = out->volume_r;
10123 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10124 compress_pause(out->compr);
10125 out_set_compr_volume(&out->stream, (float)0, (float)0);
10126 out->a2dp_compress_mute = true;
10127 select_devices(adev, out->usecase);
10128 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10129 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010130 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010131 out->volume_l = left_p;
10132 out->volume_r = right_p;
10133 }
Zhou Songc576a452019-09-09 14:17:40 +080010134 pthread_mutex_unlock(&out->compr_mute_lock);
10135 } else {
10136 // tear down a2dp path for non offloaded streams
10137 if (audio_extn_a2dp_source_is_suspended())
10138 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010139 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010140 }
10141 ALOGV("%s: exit", __func__);
10142 return 0;
10143}
10144
10145int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10146{
10147 int ret = 0;
10148
10149 lock_output_stream(out);
10150 pthread_mutex_lock(&adev->lock);
10151
10152 ret = check_a2dp_restore_l(adev, out, restore);
10153
10154 pthread_mutex_unlock(&adev->lock);
10155 pthread_mutex_unlock(&out->lock);
10156 return ret;
10157}
10158
Haynes Mathew George01156f92018-04-13 15:29:54 -070010159void adev_on_battery_status_changed(bool charging)
10160{
10161 pthread_mutex_lock(&adev->lock);
10162 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10163 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010164 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010165 pthread_mutex_unlock(&adev->lock);
10166}
10167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010168static int adev_open(const hw_module_t *module, const char *name,
10169 hw_device_t **device)
10170{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010171 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010172 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010173 char mixer_ctl_name[128] = {0};
10174 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010175
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010176 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010177 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10178
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010179 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010180 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010181 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010182 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010183 ALOGD("%s: returning existing instance of adev", __func__);
10184 ALOGD("%s: exit", __func__);
10185 pthread_mutex_unlock(&adev_init_lock);
10186 return 0;
10187 }
10188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010189 adev = calloc(1, sizeof(struct audio_device));
10190
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010191 if (!adev) {
10192 pthread_mutex_unlock(&adev_init_lock);
10193 return -ENOMEM;
10194 }
10195
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010196 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10197
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010198 // register audio ext hidl at the earliest
10199 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010200#ifdef DYNAMIC_LOG_ENABLED
10201 register_for_dynamic_logging("hal");
10202#endif
10203
Derek Chenf939fb72018-11-13 13:34:41 -080010204 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010205 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010206 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10207 maj_version = atoi(value);
10208
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010209 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010210 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010211 adev->device.common.module = (struct hw_module_t *)module;
10212 adev->device.common.close = adev_close;
10213
10214 adev->device.init_check = adev_init_check;
10215 adev->device.set_voice_volume = adev_set_voice_volume;
10216 adev->device.set_master_volume = adev_set_master_volume;
10217 adev->device.get_master_volume = adev_get_master_volume;
10218 adev->device.set_master_mute = adev_set_master_mute;
10219 adev->device.get_master_mute = adev_get_master_mute;
10220 adev->device.set_mode = adev_set_mode;
10221 adev->device.set_mic_mute = adev_set_mic_mute;
10222 adev->device.get_mic_mute = adev_get_mic_mute;
10223 adev->device.set_parameters = adev_set_parameters;
10224 adev->device.get_parameters = adev_get_parameters;
10225 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10226 adev->device.open_output_stream = adev_open_output_stream;
10227 adev->device.close_output_stream = adev_close_output_stream;
10228 adev->device.open_input_stream = adev_open_input_stream;
10229 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010230 adev->device.create_audio_patch = adev_create_audio_patch;
10231 adev->device.release_audio_patch = adev_release_audio_patch;
10232 adev->device.get_audio_port = adev_get_audio_port;
10233 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010234 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010235 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010236
10237 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010238 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010239 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010240 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010241 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010242 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010243 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010244 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010245 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010246 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010247 /* Init audio and voice feature */
10248 audio_extn_feature_init();
10249 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010250 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010251 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010252 list_init(&adev->active_inputs_list);
10253 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010254 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010255 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10256 audio_extn_utils_hash_eq);
10257 if (!adev->io_streams_map) {
10258 ALOGE("%s: Could not create io streams map", __func__);
10259 ret = -ENOMEM;
10260 goto adev_open_err;
10261 }
10262 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10263 audio_extn_utils_hash_eq);
10264 if (!adev->patch_map) {
10265 ALOGE("%s: Could not create audio patch map", __func__);
10266 ret = -ENOMEM;
10267 goto adev_open_err;
10268 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010269 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010270 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010271 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010272 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010273 adev->perf_lock_opts[0] = 0x101;
10274 adev->perf_lock_opts[1] = 0x20E;
10275 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010276 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010277 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010278 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010279 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010281 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010282 adev->platform = platform_init(adev);
10283 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010284 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010285 ret = -EINVAL;
10286 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010287 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010288
Aalique Grahame22e49102018-12-18 14:23:57 -080010289 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010290 if (audio_extn_qap_is_enabled()) {
10291 ret = audio_extn_qap_init(adev);
10292 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010293 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010294 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010295 }
10296 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10297 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10298 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010299
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010300 if (audio_extn_qaf_is_enabled()) {
10301 ret = audio_extn_qaf_init(adev);
10302 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010303 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010304 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010305 }
10306
10307 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10308 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10309 }
10310
Derek Chenae7b0342019-02-08 15:17:04 -080010311 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010312 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10313
Eric Laurentc4aef752013-09-12 17:45:53 -070010314 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10315 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10316 if (adev->visualizer_lib == NULL) {
10317 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10318 } else {
10319 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10320 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010321 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010322 "visualizer_hal_start_output");
10323 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010324 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010325 "visualizer_hal_stop_output");
10326 }
10327 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010328 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010329 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010330 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010331 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010332 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010333 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010334
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010335 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10336 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10337 if (adev->offload_effects_lib == NULL) {
10338 ALOGE("%s: DLOPEN failed for %s", __func__,
10339 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10340 } else {
10341 ALOGV("%s: DLOPEN successful for %s", __func__,
10342 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10343 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010344 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010345 "offload_effects_bundle_hal_start_output");
10346 adev->offload_effects_stop_output =
10347 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10348 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010349 adev->offload_effects_set_hpx_state =
10350 (int (*)(bool))dlsym(adev->offload_effects_lib,
10351 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010352 adev->offload_effects_get_parameters =
10353 (void (*)(struct str_parms *, struct str_parms *))
10354 dlsym(adev->offload_effects_lib,
10355 "offload_effects_bundle_get_parameters");
10356 adev->offload_effects_set_parameters =
10357 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10358 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010359 }
10360 }
10361
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010362 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10363 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10364 if (adev->adm_lib == NULL) {
10365 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10366 } else {
10367 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10368 adev->adm_init = (adm_init_t)
10369 dlsym(adev->adm_lib, "adm_init");
10370 adev->adm_deinit = (adm_deinit_t)
10371 dlsym(adev->adm_lib, "adm_deinit");
10372 adev->adm_register_input_stream = (adm_register_input_stream_t)
10373 dlsym(adev->adm_lib, "adm_register_input_stream");
10374 adev->adm_register_output_stream = (adm_register_output_stream_t)
10375 dlsym(adev->adm_lib, "adm_register_output_stream");
10376 adev->adm_deregister_stream = (adm_deregister_stream_t)
10377 dlsym(adev->adm_lib, "adm_deregister_stream");
10378 adev->adm_request_focus = (adm_request_focus_t)
10379 dlsym(adev->adm_lib, "adm_request_focus");
10380 adev->adm_abandon_focus = (adm_abandon_focus_t)
10381 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010382 adev->adm_set_config = (adm_set_config_t)
10383 dlsym(adev->adm_lib, "adm_set_config");
10384 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10385 dlsym(adev->adm_lib, "adm_request_focus_v2");
10386 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10387 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10388 adev->adm_on_routing_change = (adm_on_routing_change_t)
10389 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010390 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10391 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010392 }
10393 }
10394
Aalique Grahame22e49102018-12-18 14:23:57 -080010395 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010396 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010397 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010398 //initialize this to false for now,
10399 //this will be set to true through set param
10400 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010401
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010402 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010403 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010404
10405 if (k_enable_extended_precision)
10406 adev_verify_devices(adev);
10407
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010408 adev->dsp_bit_width_enforce_mode =
10409 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010410
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010411 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10412 &adev->streams_output_cfg_list,
10413 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010414
Kiran Kandi910e1862013-10-29 13:29:42 -070010415 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010416
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010417 int trial;
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010418 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010419 trial = atoi(value);
10420 if (period_size_is_plausible_for_low_latency(trial)) {
10421 pcm_config_low_latency.period_size = trial;
10422 pcm_config_low_latency.start_threshold = trial / 4;
10423 pcm_config_low_latency.avail_min = trial / 4;
10424 configured_low_latency_capture_period_size = trial;
10425 }
10426 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010427 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10428 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010429 trial = atoi(value);
10430 if (period_size_is_plausible_for_low_latency(trial)) {
10431 configured_low_latency_capture_period_size = trial;
10432 }
10433 }
10434
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010435 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10436
Eric Laurent4b084132018-10-19 17:33:43 -070010437 adev->camera_orientation = CAMERA_DEFAULT;
10438
Manisha Agarwalc75a0202019-12-06 18:48:25 +053010439 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010440 af_period_multiplier = atoi(value);
10441 if (af_period_multiplier < 0)
10442 af_period_multiplier = 2;
10443 else if (af_period_multiplier > 4)
10444 af_period_multiplier = 4;
10445
10446 ALOGV("new period_multiplier = %d", af_period_multiplier);
10447 }
10448
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010449 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010450
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010451 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010452 pthread_mutex_unlock(&adev_init_lock);
10453
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010454 if (adev->adm_init)
10455 adev->adm_data = adev->adm_init();
10456
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010457 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010458 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010459 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010460
10461 audio_extn_snd_mon_init();
10462 pthread_mutex_lock(&adev->lock);
10463 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10464 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010465 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10466 /*
10467 * if the battery state callback happens before charging can be queried,
10468 * it will be guarded with the adev->lock held in the cb function and so
10469 * the callback value will reflect the latest state
10470 */
10471 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010472 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010473 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010474 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010475 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010476 /* Allocate memory for Device config params */
10477 adev->device_cfg_params = (struct audio_device_config_param*)
10478 calloc(platform_get_max_codec_backend(),
10479 sizeof(struct audio_device_config_param));
10480 if (adev->device_cfg_params == NULL)
10481 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010482
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010483 /*
10484 * Check if new PSPD matrix mixer control is supported. If not
10485 * supported, then set flag so that old mixer ctrl is sent while
10486 * sending pspd coefficients on older kernel version. Query mixer
10487 * control for default pcm id and channel value one.
10488 */
10489 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10490 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10491
10492 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10493 if (!ctl) {
10494 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10495 __func__, mixer_ctl_name);
10496 adev->use_old_pspd_mix_ctrl = true;
10497 }
10498
Eric Laurent994a6932013-07-17 11:51:42 -070010499 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010500 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010501
10502adev_open_err:
10503 free_map(adev->patch_map);
10504 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010505 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010506 pthread_mutex_destroy(&adev->lock);
10507 free(adev);
10508 adev = NULL;
10509 *device = NULL;
10510 pthread_mutex_unlock(&adev_init_lock);
10511 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010512}
10513
10514static struct hw_module_methods_t hal_module_methods = {
10515 .open = adev_open,
10516};
10517
10518struct audio_module HAL_MODULE_INFO_SYM = {
10519 .common = {
10520 .tag = HARDWARE_MODULE_TAG,
10521 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10522 .hal_api_version = HARDWARE_HAL_API_VERSION,
10523 .id = AUDIO_HARDWARE_MODULE_ID,
10524 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010525 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010526 .methods = &hal_module_methods,
10527 },
10528};