blob: b2d87a95eca806ebcfccd5112fb1bdaa4d70b23e [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
3068 if (get_usecase_from_list(adev, in->usecase) != NULL) {
3069 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
3070 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08003071 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07003072 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07003073
Eric Laurentb23d5282013-05-14 15:27:20 -07003074 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003075 if (in->pcm_device_id < 0) {
3076 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
3077 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08003078 ret = -EINVAL;
3079 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003080 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003081
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003082 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003083
3084 if (!uc_info) {
3085 ret = -ENOMEM;
3086 goto error_config;
3087 }
3088
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003089 uc_info->id = in->usecase;
3090 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003091 uc_info->stream.in = in;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003092 list_init(&uc_info->device_list);
3093 assign_devices(&uc_info->device_list, &in->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003094 uc_info->in_snd_device = SND_DEVICE_NONE;
3095 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003096
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003097 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003098 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303099 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3100 adev->perf_lock_opts,
3101 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003102 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003103
Derek Chenea197282019-01-07 17:35:01 -08003104 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3105 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003106
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05303107 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
3108
Haynes Mathew George16081042017-05-31 17:16:49 -07003109 if (audio_extn_cin_attached_usecase(in->usecase)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05303110 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303111 if (ret)
3112 goto error_open;
3113 else
3114 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003115 }
3116
Haynes Mathew George16081042017-05-31 17:16:49 -07003117 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003118 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003119 ALOGE("%s: pcm stream not ready", __func__);
3120 goto error_open;
3121 }
3122 ret = pcm_start(in->pcm);
3123 if (ret < 0) {
3124 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3125 goto error_open;
3126 }
3127 } else {
3128 unsigned int flags = PCM_IN | PCM_MONOTONIC;
3129 unsigned int pcm_open_retry_count = 0;
3130
3131 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
3132 flags |= PCM_MMAP | PCM_NOIRQ;
3133 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
3134 } else if (in->realtime) {
3135 flags |= PCM_MMAP | PCM_NOIRQ;
3136 }
3137
Garmond Leunge2433c32017-09-28 21:51:22 -07003138 if (audio_extn_ffv_get_stream() == in) {
3139 ALOGD("%s: ffv stream, update pcm config", __func__);
3140 audio_extn_ffv_update_pcm_config(&config);
3141 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003142 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
3143 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
3144
3145 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003146 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003147 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003148 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003149 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303150 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303151 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3152 adev->card_status = CARD_STATUS_OFFLINE;
3153 in->card_status = CARD_STATUS_OFFLINE;
3154 ret = -EIO;
3155 goto error_open;
3156 }
3157
Haynes Mathew George16081042017-05-31 17:16:49 -07003158 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3159 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3160 if (in->pcm != NULL) {
3161 pcm_close(in->pcm);
3162 in->pcm = NULL;
3163 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003164 if (pcm_open_retry_count == 0) {
Haynes Mathew George16081042017-05-31 17:16:49 -07003165 ret = -EIO;
3166 goto error_open;
3167 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003168 pcm_open_retry_count--;
Haynes Mathew George16081042017-05-31 17:16:49 -07003169 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3170 continue;
3171 }
3172 break;
3173 }
3174
3175 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003176 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003177 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003178 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003179 if (ret < 0) {
3180 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3181 pcm_close(in->pcm);
3182 in->pcm = NULL;
3183 goto error_open;
3184 }
3185 register_in_stream(in);
3186 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003187 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003188 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003189 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003190 if (ret < 0) {
3191 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003192 pcm_close(in->pcm);
3193 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003194 goto error_open;
3195 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003196 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003197 }
3198
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003199 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003200 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3201 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003202
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003203 if (is_loopback_input_device(get_device_types(&in->device_list)))
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303204 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3205
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303206done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003207 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303208 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003209 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303210 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003211 return ret;
3212
3213error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003214 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303215 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003216 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003217
Eric Laurentc8400632013-02-14 19:04:54 -08003218error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303219 /*
3220 * sleep 50ms to allow sufficient time for kernel
3221 * drivers to recover incases like SSR.
3222 */
3223 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003224 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303225 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003226 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003227}
3228
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003229void lock_input_stream(struct stream_in *in)
3230{
3231 pthread_mutex_lock(&in->pre_lock);
3232 pthread_mutex_lock(&in->lock);
3233 pthread_mutex_unlock(&in->pre_lock);
3234}
3235
3236void lock_output_stream(struct stream_out *out)
3237{
3238 pthread_mutex_lock(&out->pre_lock);
3239 pthread_mutex_lock(&out->lock);
3240 pthread_mutex_unlock(&out->pre_lock);
3241}
3242
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003243/* must be called with out->lock locked */
3244static int send_offload_cmd_l(struct stream_out* out, int command)
3245{
3246 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3247
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003248 if (!cmd) {
3249 ALOGE("failed to allocate mem for command 0x%x", command);
3250 return -ENOMEM;
3251 }
3252
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003253 ALOGVV("%s %d", __func__, command);
3254
3255 cmd->cmd = command;
3256 list_add_tail(&out->offload_cmd_list, &cmd->node);
3257 pthread_cond_signal(&out->offload_cond);
3258 return 0;
3259}
3260
3261/* must be called iwth out->lock locked */
3262static void stop_compressed_output_l(struct stream_out *out)
3263{
3264 out->offload_state = OFFLOAD_STATE_IDLE;
3265 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003266 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003267 if (out->compr != NULL) {
3268 compress_stop(out->compr);
3269 while (out->offload_thread_blocked) {
3270 pthread_cond_wait(&out->cond, &out->lock);
3271 }
3272 }
3273}
3274
Varun Balaraje49253e2017-07-06 19:48:56 +05303275bool is_interactive_usecase(audio_usecase_t uc_id)
3276{
3277 unsigned int i;
3278 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3279 if (uc_id == interactive_usecases[i])
3280 return true;
3281 }
3282 return false;
3283}
3284
3285static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3286{
3287 audio_usecase_t ret_uc = USECASE_INVALID;
3288 unsigned int intract_uc_index;
3289 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3290
3291 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3292 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3293 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3294 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3295 ret_uc = interactive_usecases[intract_uc_index];
3296 break;
3297 }
3298 }
3299
3300 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3301 return ret_uc;
3302}
3303
3304static void free_interactive_usecase(struct audio_device *adev,
3305 audio_usecase_t uc_id)
3306{
3307 unsigned int interact_uc_index;
3308 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3309
3310 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3311 if (interactive_usecases[interact_uc_index] == uc_id) {
3312 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3313 break;
3314 }
3315 }
3316 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3317}
3318
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003319bool is_offload_usecase(audio_usecase_t uc_id)
3320{
3321 unsigned int i;
3322 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3323 if (uc_id == offload_usecases[i])
3324 return true;
3325 }
3326 return false;
3327}
3328
Dhananjay Kumarac341582017-02-23 23:42:25 +05303329static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003330{
vivek mehta446c3962015-09-14 10:57:35 -07003331 audio_usecase_t ret_uc = USECASE_INVALID;
3332 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003333 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003334 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303335 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003336 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3337 else
3338 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003339
vivek mehta446c3962015-09-14 10:57:35 -07003340 pthread_mutex_lock(&adev->lock);
3341 if (get_usecase_from_list(adev, ret_uc) != NULL)
3342 ret_uc = USECASE_INVALID;
3343 pthread_mutex_unlock(&adev->lock);
3344
3345 return ret_uc;
3346 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003347
3348 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003349 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3350 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3351 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3352 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003353 break;
3354 }
3355 }
vivek mehta446c3962015-09-14 10:57:35 -07003356
3357 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3358 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003359}
3360
3361static void free_offload_usecase(struct audio_device *adev,
3362 audio_usecase_t uc_id)
3363{
vivek mehta446c3962015-09-14 10:57:35 -07003364 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003365 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003366
3367 if (!adev->multi_offload_enable)
3368 return;
3369
3370 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3371 if (offload_usecases[offload_uc_index] == uc_id) {
3372 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003373 break;
3374 }
3375 }
3376 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3377}
3378
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003379static void *offload_thread_loop(void *context)
3380{
3381 struct stream_out *out = (struct stream_out *) context;
3382 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003383 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003384
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003385 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08003386 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003387 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3388
3389 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003390 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003391 out->offload_state = OFFLOAD_STATE_IDLE;
3392 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003393 for (;;) {
3394 struct offload_cmd *cmd = NULL;
3395 stream_callback_event_t event;
3396 bool send_callback = false;
3397
3398 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3399 __func__, list_empty(&out->offload_cmd_list),
3400 out->offload_state);
3401 if (list_empty(&out->offload_cmd_list)) {
3402 ALOGV("%s SLEEPING", __func__);
3403 pthread_cond_wait(&out->offload_cond, &out->lock);
3404 ALOGV("%s RUNNING", __func__);
3405 continue;
3406 }
3407
3408 item = list_head(&out->offload_cmd_list);
3409 cmd = node_to_item(item, struct offload_cmd, node);
3410 list_remove(item);
3411
3412 ALOGVV("%s STATE %d CMD %d out->compr %p",
3413 __func__, out->offload_state, cmd->cmd, out->compr);
3414
3415 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3416 free(cmd);
3417 break;
3418 }
3419
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003420 // allow OFFLOAD_CMD_ERROR reporting during standby
3421 // this is needed to handle failures during compress_open
3422 // Note however that on a pause timeout, the stream is closed
3423 // and no offload usecase will be active. Therefore this
3424 // special case is needed for compress_open failures alone
3425 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3426 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003427 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003428 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003429 pthread_cond_signal(&out->cond);
3430 continue;
3431 }
3432 out->offload_thread_blocked = true;
3433 pthread_mutex_unlock(&out->lock);
3434 send_callback = false;
3435 switch(cmd->cmd) {
3436 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003437 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003438 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003439 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003440 send_callback = true;
3441 event = STREAM_CBK_EVENT_WRITE_READY;
3442 break;
3443 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003444 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303445 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003446 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303447 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003448 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303449 if (ret < 0)
3450 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303451 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303452 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003453 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003454 else
3455 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003456 if (-ENETRESET != ret && !(-EINTR == ret &&
3457 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303458 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303459 pthread_mutex_lock(&out->lock);
3460 out->send_new_metadata = 1;
3461 out->send_next_track_params = true;
3462 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303463 event = STREAM_CBK_EVENT_DRAIN_READY;
3464 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3465 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303466 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003467 break;
3468 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003469 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003470 ret = compress_drain(out->compr);
3471 ALOGD("copl(%p):out of compress_drain", out);
3472 // EINTR check avoids drain interruption due to SSR
3473 if (-ENETRESET != ret && !(-EINTR == ret &&
3474 CARD_STATUS_OFFLINE == out->card_status)) {
3475 send_callback = true;
3476 event = STREAM_CBK_EVENT_DRAIN_READY;
3477 } else
3478 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003479 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303480 case OFFLOAD_CMD_ERROR:
3481 ALOGD("copl(%p): sending error callback to AF", out);
3482 send_callback = true;
3483 event = STREAM_CBK_EVENT_ERROR;
3484 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003485 default:
3486 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3487 break;
3488 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003489 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003490 out->offload_thread_blocked = false;
3491 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003492 if (send_callback && out->client_callback) {
3493 ALOGVV("%s: sending client_callback event %d", __func__, event);
3494 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003495 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003496 free(cmd);
3497 }
3498
3499 pthread_cond_signal(&out->cond);
3500 while (!list_empty(&out->offload_cmd_list)) {
3501 item = list_head(&out->offload_cmd_list);
3502 list_remove(item);
3503 free(node_to_item(item, struct offload_cmd, node));
3504 }
3505 pthread_mutex_unlock(&out->lock);
3506
3507 return NULL;
3508}
3509
3510static int create_offload_callback_thread(struct stream_out *out)
3511{
3512 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3513 list_init(&out->offload_cmd_list);
3514 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3515 offload_thread_loop, out);
3516 return 0;
3517}
3518
3519static int destroy_offload_callback_thread(struct stream_out *out)
3520{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003521 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003522 stop_compressed_output_l(out);
3523 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3524
3525 pthread_mutex_unlock(&out->lock);
3526 pthread_join(out->offload_thread, (void **) NULL);
3527 pthread_cond_destroy(&out->offload_cond);
3528
3529 return 0;
3530}
3531
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532static int stop_output_stream(struct stream_out *out)
3533{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303534 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535 struct audio_usecase *uc_info;
3536 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003537 bool has_voip_usecase =
3538 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539
Eric Laurent994a6932013-07-17 11:51:42 -07003540 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003541 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003542 uc_info = get_usecase_from_list(adev, out->usecase);
3543 if (uc_info == NULL) {
3544 ALOGE("%s: Could not find the usecase (%d) in the list",
3545 __func__, out->usecase);
3546 return -EINVAL;
3547 }
3548
Derek Chenea197282019-01-07 17:35:01 -08003549 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3550 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003551
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003552 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303553 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003554 if (adev->visualizer_stop_output != NULL)
3555 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003556
3557 audio_extn_dts_remove_state_notifier_node(out->usecase);
3558
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003559 if (adev->offload_effects_stop_output != NULL)
3560 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003561 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3562 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3563 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003564 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003565
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003566 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3567 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003568 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003569 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003570
Eric Laurent150dbfe2013-02-27 14:31:02 -08003571 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003572 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003573
3574 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003575 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003576
Aalique Grahame22e49102018-12-18 14:23:57 -08003577 audio_extn_extspk_update(adev->extspk);
3578
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003579 if (is_offload_usecase(out->usecase)) {
3580 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3581 adev->dsp_bit_width_enforce_mode,
3582 false);
3583 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003584 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003585 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3586 false);
3587
3588 if (ret != 0)
3589 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3590 /* default service interval was successfully updated,
3591 reopen USB backend with new service interval */
3592 ret = 0;
3593 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003594
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003595 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303596 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003597 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303598 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003599 ALOGV("Disable passthrough , reset mixer to pcm");
3600 /* NO_PASSTHROUGH */
Meng Wang4c32fb42020-01-16 17:57:11 +08003601#ifdef AUDIO_GKI_ENABLED
3602 /* out->compr_config.codec->reserved[0] is for compr_passthr */
3603 out->compr_config.codec->reserved[0] = 0;
3604#else
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003605 out->compr_config.codec->compr_passthr = 0;
Meng Wang4c32fb42020-01-16 17:57:11 +08003606#endif
Mingming Yin21854652016-04-13 11:54:02 -07003607 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003608 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3609 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003610
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303611 /* Must be called after removing the usecase from list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003612 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL))
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303613 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303614
Manish Dewangan21a850a2017-08-14 12:03:55 +05303615 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003616 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3617 if (ret < 0)
3618 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3619 }
3620
juyuchen2d415992018-11-16 14:15:16 +08003621 /* 1) media + voip output routing to handset must route media back to
3622 speaker when voip stops.
3623 2) trigger voip input to reroute when voip output changes to
3624 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003625 if (has_voip_usecase ||
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003626 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003627 struct listnode *node;
3628 struct audio_usecase *usecase;
3629 list_for_each(node, &adev->usecase_list) {
3630 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003631 if ((usecase->type == PCM_CAPTURE &&
3632 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3633 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003634 continue;
3635
3636 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3637 __func__, usecase->id, use_case_table[usecase->id],
3638 out->usecase, use_case_table[out->usecase]);
3639 select_devices(adev, usecase->id);
3640 }
3641 }
3642
Garmond Leung5fd0b552018-04-17 11:56:12 -07003643 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003644 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003645 return ret;
3646}
3647
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003648struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3649 unsigned int flags, unsigned int pcm_open_retry_count,
3650 struct pcm_config *config)
3651{
3652 struct pcm* pcm = NULL;
3653
3654 while (1) {
3655 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3656 if (pcm == NULL || !pcm_is_ready(pcm)) {
3657 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3658 if (pcm != NULL) {
3659 pcm_close(pcm);
3660 pcm = NULL;
3661 }
Weiyin Jiang72197252019-10-09 11:49:32 +08003662 if (pcm_open_retry_count == 0)
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003663 return NULL;
3664
Weiyin Jiang72197252019-10-09 11:49:32 +08003665 pcm_open_retry_count--;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003666 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3667 continue;
3668 }
3669 break;
3670 }
3671
3672 if (pcm_is_ready(pcm)) {
3673 int ret = pcm_prepare(pcm);
3674 if (ret < 0) {
3675 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3676 pcm_close(pcm);
3677 pcm = NULL;
3678 }
3679 }
3680
3681 return pcm;
3682}
3683
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684int start_output_stream(struct stream_out *out)
3685{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003686 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687 struct audio_usecase *uc_info;
3688 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003689 char mixer_ctl_name[128];
3690 struct mixer_ctl *ctl = NULL;
3691 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303692 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003693 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003694
Haynes Mathew George380745d2017-10-04 15:27:45 -07003695 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003696 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3697 ret = -EINVAL;
3698 goto error_config;
3699 }
3700
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003701 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303702 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003703 get_device_types(&out->device_list), is_haptic_usecase);
3704
3705 bool is_speaker_active = compare_device_type(&out->device_list,
3706 AUDIO_DEVICE_OUT_SPEAKER);
3707 bool is_speaker_safe_active = compare_device_type(&out->device_list,
3708 AUDIO_DEVICE_OUT_SPEAKER_SAFE);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303709
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303710 if (CARD_STATUS_OFFLINE == out->card_status ||
3711 CARD_STATUS_OFFLINE == adev->card_status) {
3712 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303713 ret = -EIO;
Mingshu Pang5fc696f2020-02-28 12:32:00 +08003714 goto error_fatal;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303715 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303716
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003717 //Update incall music usecase to reflect correct voice session
3718 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3719 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3720 if (ret != 0) {
3721 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3722 __func__, ret);
3723 goto error_config;
3724 }
3725 }
3726
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003727 if (is_a2dp_out_device_type(&out->device_list)) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003728 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003729 if (is_speaker_active || is_speaker_safe_active) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303730 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303731 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303732 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3733 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3734 ret = -EAGAIN;
3735 goto error_config;
3736 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303737 }
3738 }
3739 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003740 if (is_sco_out_device_type(&out->device_list)) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303741 if (!adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003742 if (is_speaker_active) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303743 //combo usecase just by pass a2dp
3744 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003745 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303746 } else {
3747 ALOGE("%s: SCO profile is not ready, return error", __func__);
3748 ret = -EAGAIN;
3749 goto error_config;
3750 }
3751 }
3752 }
3753
Eric Laurentb23d5282013-05-14 15:27:20 -07003754 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003755 if (out->pcm_device_id < 0) {
3756 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3757 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003758 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003759 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003760 }
3761
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003762 if (is_haptic_usecase) {
3763 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3764 if (adev->haptic_pcm_device_id < 0) {
3765 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3766 __func__, adev->haptic_pcm_device_id, out->usecase);
3767 ret = -EINVAL;
3768 goto error_config;
3769 }
3770 }
3771
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003772 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003773
3774 if (!uc_info) {
3775 ret = -ENOMEM;
3776 goto error_config;
3777 }
3778
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003779 uc_info->id = out->usecase;
3780 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003781 uc_info->stream.out = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003782 list_init(&uc_info->device_list);
3783 assign_devices(&uc_info->device_list, &out->device_list);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003784 uc_info->in_snd_device = SND_DEVICE_NONE;
3785 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003786
3787 /* This must be called before adding this usecase to the list */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003788 if (is_usb_out_device_type(&out->device_list)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07003789 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3790 /* USB backend is not reopened immediately.
3791 This is eventually done as part of select_devices */
3792 }
3793
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003794 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003795
Wei Wangf7ca6c92017-11-21 14:51:20 -08003796 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303797 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3798 adev->perf_lock_opts,
3799 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303800
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003801 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303802 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303803 if (audio_extn_passthru_is_enabled() &&
3804 audio_extn_passthru_is_passthrough_stream(out)) {
3805 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303806 }
3807 }
3808
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003809 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003810 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303811 if (!a2dp_combo) {
3812 check_a2dp_restore_l(adev, out, false);
3813 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003814 struct listnode dev;
3815 list_init(&dev);
3816 assign_devices(&dev, &out->device_list);
3817 if (compare_device_type(&dev, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
3818 reassign_device_list(&out->device_list,
3819 AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aalique Grahame22e49102018-12-18 14:23:57 -08003820 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003821 reassign_device_list(&out->device_list,
3822 AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303823 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003824 assign_devices(&out->device_list, &dev);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303825 }
3826 } else {
3827 select_devices(adev, out->usecase);
3828 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003829
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003830 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3831 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003832 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003833 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003834
Derek Chenea197282019-01-07 17:35:01 -08003835 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3836 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003837
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003838 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3839 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003840
3841 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003842 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003843 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3844 ALOGE("%s: pcm stream not ready", __func__);
3845 goto error_open;
3846 }
3847 ret = pcm_start(out->pcm);
3848 if (ret < 0) {
3849 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3850 goto error_open;
3851 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003852 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003853 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003854 unsigned int flags = PCM_OUT;
3855 unsigned int pcm_open_retry_count = 0;
3856 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3857 flags |= PCM_MMAP | PCM_NOIRQ;
3858 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003859 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003860 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003861 } else
3862 flags |= PCM_MONOTONIC;
3863
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003864 if ((adev->vr_audio_mode_enabled) &&
3865 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3866 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3867 "PCM_Dev %d Topology", out->pcm_device_id);
3868 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3869 if (!ctl) {
3870 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3871 __func__, mixer_ctl_name);
3872 } else {
3873 //if success use ULLPP
3874 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3875 __func__, mixer_ctl_name, out->pcm_device_id);
3876 //There is a still a possibility that some sessions
3877 // that request for FAST|RAW when 3D audio is active
3878 //can go through ULLPP. Ideally we expects apps to
3879 //listen to audio focus and stop concurrent playback
3880 //Also, we will look for mode flag (voice_in_communication)
3881 //before enabling the realtime flag.
3882 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3883 }
3884 }
3885
Surendar Karka91fa3682018-07-02 18:12:12 +05303886 if (out->realtime)
3887 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3888 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3889
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003890 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3891 flags, pcm_open_retry_count,
3892 &(out->config));
3893 if (out->pcm == NULL) {
3894 ret = -EIO;
3895 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003896 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003897
3898 if (is_haptic_usecase) {
3899 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3900 adev->haptic_pcm_device_id,
3901 flags, pcm_open_retry_count,
3902 &(adev->haptics_config));
3903 // failure to open haptics pcm shouldnt stop audio,
3904 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003905
3906 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3907 ALOGD("%s: enable haptic audio synchronization", __func__);
3908 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3909 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003910 }
3911
Surendar Karka91fa3682018-07-02 18:12:12 +05303912 if (!out->realtime)
3913 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303914 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003915
Zhou Song2b8f28f2017-09-11 10:51:38 +08003916 // apply volume for voip playback after path is set up
3917 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3918 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303919 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3920 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303921 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3922 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003923 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3924 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303925 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003926 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003927 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303928 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003929 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3930 adev->dsp_bit_width_enforce_mode,
3931 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003933 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003934 out->compr = compress_open(adev->snd_card,
3935 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003936 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003937 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303938 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303939 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3940 adev->card_status = CARD_STATUS_OFFLINE;
3941 out->card_status = CARD_STATUS_OFFLINE;
3942 ret = -EIO;
3943 goto error_open;
3944 }
3945
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003946 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003947 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003948 compress_close(out->compr);
3949 out->compr = NULL;
3950 ret = -EIO;
3951 goto error_open;
3952 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303953 /* compress_open sends params of the track, so reset the flag here */
3954 out->is_compr_metadata_avail = false;
3955
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003956 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003957 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003958
Fred Oh3f43e742015-03-04 18:42:34 -08003959 /* Since small bufs uses blocking writes, a write will be blocked
3960 for the default max poll time (20s) in the event of an SSR.
3961 Reduce the poll time to observe and deal with SSR faster.
3962 */
Ashish Jain5106d362016-05-11 19:23:33 +05303963 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003964 compress_set_max_poll_wait(out->compr, 1000);
3965 }
3966
Manish Dewangan69426c82017-01-30 17:35:36 +05303967 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303968 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303969
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003970 audio_extn_dts_create_state_notifier_node(out->usecase);
3971 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3972 popcount(out->channel_mask),
3973 out->playback_started);
3974
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003975#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303976 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003977 audio_extn_dolby_send_ddp_endp_params(adev);
3978#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303979 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3980 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003981 if (adev->visualizer_start_output != NULL)
3982 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3983 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303984 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003985 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003986 }
Derek Chenf13dd492018-11-13 14:53:51 -08003987
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08003988 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf13dd492018-11-13 14:53:51 -08003989 /* Update cached volume from media to offload/direct stream */
3990 struct listnode *node = NULL;
3991 list_for_each(node, &adev->active_outputs_list) {
3992 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3993 streams_output_ctxt_t,
3994 list);
3995 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3996 out->volume_l = out_ctxt->output->volume_l;
3997 out->volume_r = out_ctxt->output->volume_r;
3998 }
3999 }
4000 out_set_compr_volume(&out->stream,
4001 out->volume_l, out->volume_r);
4002 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004003 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004004
4005 if (ret == 0) {
4006 register_out_stream(out);
4007 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07004008 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
4009 ALOGE("%s: pcm stream not ready", __func__);
4010 goto error_open;
4011 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07004012 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004013 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004014 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004015 if (ret < 0)
4016 goto error_open;
4017 }
4018 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004019 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304020 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07004021 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004022
vivek mehtad15d2bf2019-05-17 13:35:10 -07004023 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
4024 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4025 audio_low_latency_hint_start();
4026 }
4027
Manish Dewangan21a850a2017-08-14 12:03:55 +05304028 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07004029 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07004030 if (ret < 0)
4031 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
4032 }
4033
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004034 // consider a scenario where on pause lower layers are tear down.
4035 // so on resume, swap mixer control need to be sent only when
4036 // backend is active, hence rather than sending from enable device
4037 // sending it from start of streamtream
4038
4039 platform_set_swap_channels(adev, true);
4040
Haynes Mathew George380745d2017-10-04 15:27:45 -07004041 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304042 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004043 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004044error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004045 if (adev->haptic_pcm) {
4046 pcm_close(adev->haptic_pcm);
4047 adev->haptic_pcm = NULL;
4048 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08004049 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05304050 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051 stop_output_stream(out);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004052error_fatal:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05304053 /*
4054 * sleep 50ms to allow sufficient time for kernel
4055 * drivers to recover incases like SSR.
4056 */
4057 usleep(50000);
Mingshu Pang5fc696f2020-02-28 12:32:00 +08004058error_config:
Haynes Mathew George380745d2017-10-04 15:27:45 -07004059 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05304060 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08004061 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062}
4063
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064static int check_input_parameters(uint32_t sample_rate,
4065 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08004066 int channel_count,
4067 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004068{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004069 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004070
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304071 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
4072 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
4073 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07004074 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02004075 !audio_extn_compr_cap_format_supported(format) &&
4076 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004077 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004078
Aalique Grahame22e49102018-12-18 14:23:57 -08004079 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
4080 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
4081 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
4082 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
4083 return -EINVAL;
4084 }
4085
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004086 switch (channel_count) {
4087 case 1:
4088 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05304089 case 3:
4090 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004091 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07004092 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05304093 case 10:
4094 case 12:
4095 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004096 break;
4097 default:
4098 ret = -EINVAL;
4099 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004100
4101 switch (sample_rate) {
4102 case 8000:
4103 case 11025:
4104 case 12000:
4105 case 16000:
4106 case 22050:
4107 case 24000:
4108 case 32000:
4109 case 44100:
4110 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004111 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304112 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08004113 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304114 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004115 break;
4116 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004117 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004118 }
4119
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08004120 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121}
4122
Naresh Tanniru04f71882018-06-26 17:46:22 +05304123
4124/** Add a value in a list if not already present.
4125 * @return true if value was successfully inserted or already present,
4126 * false if the list is full and does not contain the value.
4127 */
4128static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
4129 for (size_t i = 0; i < list_length; i++) {
4130 if (list[i] == value) return true; // value is already present
4131 if (list[i] == 0) { // no values in this slot
4132 list[i] = value;
4133 return true; // value inserted
4134 }
4135 }
4136 return false; // could not insert value
4137}
4138
4139/** Add channel_mask in supported_channel_masks if not already present.
4140 * @return true if channel_mask was successfully inserted or already present,
4141 * false if supported_channel_masks is full and does not contain channel_mask.
4142 */
4143static void register_channel_mask(audio_channel_mask_t channel_mask,
4144 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
4145 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
4146 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
4147}
4148
4149/** Add format in supported_formats if not already present.
4150 * @return true if format was successfully inserted or already present,
4151 * false if supported_formats is full and does not contain format.
4152 */
4153static void register_format(audio_format_t format,
4154 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
4155 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
4156 "%s: stream can not declare supporting its format %x", __func__, format);
4157}
4158/** Add sample_rate in supported_sample_rates if not already present.
4159 * @return true if sample_rate was successfully inserted or already present,
4160 * false if supported_sample_rates is full and does not contain sample_rate.
4161 */
4162static void register_sample_rate(uint32_t sample_rate,
4163 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4164 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4165 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4166}
4167
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004168static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4169{
4170 uint32_t high = num1, low = num2, temp = 0;
4171
4172 if (!num1 || !num2)
4173 return 0;
4174
4175 if (num1 < num2) {
4176 high = num2;
4177 low = num1;
4178 }
4179
4180 while (low != 0) {
4181 temp = low;
4182 low = high % low;
4183 high = temp;
4184 }
4185 return (num1 * num2)/high;
4186}
4187
4188static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4189{
4190 uint32_t remainder = 0;
4191
4192 if (!multiplier)
4193 return num;
4194
4195 remainder = num % multiplier;
4196 if (remainder)
4197 num += (multiplier - remainder);
4198
4199 return num;
4200}
4201
Aalique Grahame22e49102018-12-18 14:23:57 -08004202static size_t get_stream_buffer_size(size_t duration_ms,
4203 uint32_t sample_rate,
4204 audio_format_t format,
4205 int channel_count,
4206 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207{
4208 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004209 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210
Aalique Grahame22e49102018-12-18 14:23:57 -08004211 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004212 if (is_low_latency)
4213 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304214
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004215 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004216 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217
Ralf Herzbd08d632018-09-28 15:50:49 +02004218 /* make sure the size is multiple of 32 bytes and additionally multiple of
4219 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004220 * At 48 kHz mono 16-bit PCM:
4221 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4222 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004223 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004224 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004225 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004226
4227 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004228}
4229
Aalique Grahame22e49102018-12-18 14:23:57 -08004230static size_t get_input_buffer_size(uint32_t sample_rate,
4231 audio_format_t format,
4232 int channel_count,
4233 bool is_low_latency)
4234{
4235 /* Don't know if USB HIFI in this context so use true to be conservative */
4236 if (check_input_parameters(sample_rate, format, channel_count,
4237 true /*is_usb_hifi */) != 0)
4238 return 0;
4239
4240 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4241 sample_rate,
4242 format,
4243 channel_count,
4244 is_low_latency);
4245}
4246
Derek Chenf6318be2017-06-12 17:16:24 -04004247size_t get_output_period_size(uint32_t sample_rate,
4248 audio_format_t format,
4249 int channel_count,
4250 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304251{
4252 size_t size = 0;
4253 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4254
4255 if ((duration == 0) || (sample_rate == 0) ||
4256 (bytes_per_sample == 0) || (channel_count == 0)) {
4257 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4258 bytes_per_sample, channel_count);
4259 return -EINVAL;
4260 }
4261
4262 size = (sample_rate *
4263 duration *
4264 bytes_per_sample *
4265 channel_count) / 1000;
4266 /*
4267 * To have same PCM samples for all channels, the buffer size requires to
4268 * be multiple of (number of channels * bytes per sample)
4269 * For writes to succeed, the buffer must be written at address which is multiple of 32
4270 */
4271 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4272
4273 return (size/(channel_count * bytes_per_sample));
4274}
4275
Zhou Song48453a02018-01-10 17:50:59 +08004276static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304277{
4278 uint64_t actual_frames_rendered = 0;
4279 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4280
4281 /* This adjustment accounts for buffering after app processor.
4282 * It is based on estimated DSP latency per use case, rather than exact.
4283 */
4284 int64_t platform_latency = platform_render_latency(out->usecase) *
4285 out->sample_rate / 1000000LL;
4286
Zhou Song48453a02018-01-10 17:50:59 +08004287 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304288 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4289 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4290 * hence only estimate.
4291 */
George Gao62ebc722019-07-29 16:29:44 -07004292 uint64_t signed_frames = 0;
4293 if (out->written >= kernel_buffer_size)
4294 signed_frames = out->written - kernel_buffer_size;
Ashish Jain5106d362016-05-11 19:23:33 +05304295
George Gao62ebc722019-07-29 16:29:44 -07004296 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask));
4297 if (signed_frames >= platform_latency)
4298 signed_frames = signed_frames - platform_latency;
Ashish Jain5106d362016-05-11 19:23:33 +05304299
Zhou Song48453a02018-01-10 17:50:59 +08004300 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304301 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004302 if (timestamp != NULL )
4303 *timestamp = out->writeAt;
4304 } else if (timestamp != NULL) {
4305 clock_gettime(CLOCK_MONOTONIC, timestamp);
4306 }
4307 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304308
4309 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
George Gao62ebc722019-07-29 16:29:44 -07004310 "bytes/sample %zu channel count %d", __func__, signed_frames,
Ashish Jain5106d362016-05-11 19:23:33 +05304311 (long long int)out->written, (int)kernel_buffer_size,
4312 audio_bytes_per_sample(out->compr_config.codec->format),
4313 popcount(out->channel_mask));
4314
4315 return actual_frames_rendered;
4316}
4317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004318static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4319{
4320 struct stream_out *out = (struct stream_out *)stream;
4321
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004322 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004323}
4324
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004325static int out_set_sample_rate(struct audio_stream *stream __unused,
4326 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004327{
4328 return -ENOSYS;
4329}
4330
4331static size_t out_get_buffer_size(const struct audio_stream *stream)
4332{
4333 struct stream_out *out = (struct stream_out *)stream;
4334
Varun Balaraje49253e2017-07-06 19:48:56 +05304335 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304336 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304337 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304338 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4339 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4340 else
4341 return out->compr_config.fragment_size;
4342 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004343 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304344 else if (is_offload_usecase(out->usecase) &&
4345 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304346 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004347
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004348 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004349 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004350}
4351
4352static uint32_t out_get_channels(const struct audio_stream *stream)
4353{
4354 struct stream_out *out = (struct stream_out *)stream;
4355
4356 return out->channel_mask;
4357}
4358
4359static audio_format_t out_get_format(const struct audio_stream *stream)
4360{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004361 struct stream_out *out = (struct stream_out *)stream;
4362
4363 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004364}
4365
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004366static int out_set_format(struct audio_stream *stream __unused,
4367 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004368{
4369 return -ENOSYS;
4370}
4371
4372static int out_standby(struct audio_stream *stream)
4373{
4374 struct stream_out *out = (struct stream_out *)stream;
4375 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004376 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004377
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304378 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4379 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004381 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004383 if (adev->adm_deregister_stream)
4384 adev->adm_deregister_stream(adev->adm_data, out->handle);
4385
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004386 if (is_offload_usecase(out->usecase))
4387 stop_compressed_output_l(out);
4388
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004389 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004391 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4392 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304393 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004394 pthread_mutex_unlock(&adev->lock);
4395 pthread_mutex_unlock(&out->lock);
4396 ALOGD("VOIP output entered standby");
4397 return 0;
4398 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004399 if (out->pcm) {
4400 pcm_close(out->pcm);
4401 out->pcm = NULL;
4402 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004403 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4404 do_stop = out->playback_started;
4405 out->playback_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07004406
4407 if (out->mmap_shared_memory_fd >= 0) {
4408 ALOGV("%s: closing mmap_shared_memory_fd = %d",
4409 __func__, out->mmap_shared_memory_fd);
4410 close(out->mmap_shared_memory_fd);
4411 out->mmap_shared_memory_fd = -1;
4412 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004413 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004414 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004415 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304416 out->send_next_track_params = false;
4417 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004418 out->gapless_mdata.encoder_delay = 0;
4419 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004420 if (out->compr != NULL) {
4421 compress_close(out->compr);
4422 out->compr = NULL;
4423 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004424 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004425 if (do_stop) {
4426 stop_output_stream(out);
4427 }
Lakshman Chaluvaraju06677b42019-06-24 10:04:52 +05304428 // if fm is active route on selected device in UI
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004429 audio_extn_fm_route_on_selected_device(adev, &out->device_list);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004430 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004431 }
4432 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304433 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004434 return 0;
4435}
4436
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304437static int out_on_error(struct audio_stream *stream)
4438{
4439 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004440 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304441
4442 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004443 // always send CMD_ERROR for offload streams, this
4444 // is needed e.g. when SSR happens within compress_open
4445 // since the stream is active, offload_callback_thread is also active.
4446 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4447 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004448 }
4449 pthread_mutex_unlock(&out->lock);
4450
4451 status = out_standby(&out->stream.common);
4452
4453 lock_output_stream(out);
4454 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004455 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304456 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304457
4458 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4459 ALOGD("Setting previous card status if offline");
4460 out->prev_card_status_offline = true;
4461 }
4462
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304463 pthread_mutex_unlock(&out->lock);
4464
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004465 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304466}
4467
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304468/*
4469 *standby implementation without locks, assumes that the callee already
4470 *has taken adev and out lock.
4471 */
4472int out_standby_l(struct audio_stream *stream)
4473{
4474 struct stream_out *out = (struct stream_out *)stream;
4475 struct audio_device *adev = out->dev;
4476
4477 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4478 stream, out->usecase, use_case_table[out->usecase]);
4479
4480 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004481 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304482 if (adev->adm_deregister_stream)
4483 adev->adm_deregister_stream(adev->adm_data, out->handle);
4484
4485 if (is_offload_usecase(out->usecase))
4486 stop_compressed_output_l(out);
4487
4488 out->standby = true;
4489 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4490 voice_extn_compress_voip_close_output_stream(stream);
4491 out->started = 0;
4492 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004493 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304494 return 0;
4495 } else if (!is_offload_usecase(out->usecase)) {
4496 if (out->pcm) {
4497 pcm_close(out->pcm);
4498 out->pcm = NULL;
4499 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004500 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4501 if (adev->haptic_pcm) {
4502 pcm_close(adev->haptic_pcm);
4503 adev->haptic_pcm = NULL;
4504 }
4505
4506 if (adev->haptic_buffer != NULL) {
4507 free(adev->haptic_buffer);
4508 adev->haptic_buffer = NULL;
4509 adev->haptic_buffer_size = 0;
4510 }
4511 adev->haptic_pcm_device_id = 0;
4512 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304513 } else {
4514 ALOGD("copl(%p):standby", out);
4515 out->send_next_track_params = false;
4516 out->is_compr_metadata_avail = false;
4517 out->gapless_mdata.encoder_delay = 0;
4518 out->gapless_mdata.encoder_padding = 0;
4519 if (out->compr != NULL) {
4520 compress_close(out->compr);
4521 out->compr = NULL;
4522 }
4523 }
4524 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004525 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304526 }
4527 ALOGD("%s: exit", __func__);
4528 return 0;
4529}
4530
Aalique Grahame22e49102018-12-18 14:23:57 -08004531static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004532{
Aalique Grahame22e49102018-12-18 14:23:57 -08004533 struct stream_out *out = (struct stream_out *)stream;
4534
4535 // We try to get the lock for consistency,
4536 // but it isn't necessary for these variables.
4537 // If we're not in standby, we may be blocked on a write.
4538 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4539 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4540 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4541
4542 if (locked) {
4543 pthread_mutex_unlock(&out->lock);
4544 }
4545
4546 // dump error info
4547 (void)error_log_dump(
4548 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004550 return 0;
4551}
4552
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004553static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4554{
4555 int ret = 0;
4556 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004557
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004558 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004559 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004560 return -EINVAL;
4561 }
4562
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304563 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004564
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004565 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4566 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304567 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004568 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004569 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4570 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304571 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004572 }
4573
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004574 ALOGV("%s new encoder delay %u and padding %u", __func__,
4575 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4576
4577 return 0;
4578}
4579
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004580static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4581{
4582 return out == adev->primary_output || out == adev->voice_tx_output;
4583}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004584
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304585// note: this call is safe only if the stream_cb is
4586// removed first in close_output_stream (as is done now).
4587static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4588{
4589 if (!stream || !parms)
4590 return;
4591
4592 struct stream_out *out = (struct stream_out *)stream;
4593 struct audio_device *adev = out->dev;
4594
4595 card_status_t status;
4596 int card;
4597 if (parse_snd_card_status(parms, &card, &status) < 0)
4598 return;
4599
4600 pthread_mutex_lock(&adev->lock);
4601 bool valid_cb = (card == adev->snd_card);
4602 pthread_mutex_unlock(&adev->lock);
4603
4604 if (!valid_cb)
4605 return;
4606
4607 lock_output_stream(out);
4608 if (out->card_status != status)
4609 out->card_status = status;
4610 pthread_mutex_unlock(&out->lock);
4611
4612 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4613 use_case_table[out->usecase],
4614 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4615
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304616 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304617 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304618 if (voice_is_call_state_active(adev) &&
4619 out == adev->primary_output) {
4620 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4621 pthread_mutex_lock(&adev->lock);
4622 voice_stop_call(adev);
4623 adev->mode = AUDIO_MODE_NORMAL;
4624 pthread_mutex_unlock(&adev->lock);
4625 }
4626 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304627 return;
4628}
4629
Kevin Rocardfce19002017-08-07 19:21:36 -07004630static int get_alive_usb_card(struct str_parms* parms) {
4631 int card;
4632 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4633 !audio_extn_usb_alive(card)) {
4634 return card;
4635 }
4636 return -ENODEV;
4637}
4638
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004639int route_output_stream(struct stream_out *out,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004640 struct listnode *devices)
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004641{
4642 struct audio_device *adev = out->dev;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004643 int ret = 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004644 struct listnode new_devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004645 bool bypass_a2dp = false;
4646 bool reconfig = false;
4647 unsigned long service_interval = 0;
4648
4649 ALOGD("%s: enter: usecase(%d: %s) devices %x",
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004650 __func__, out->usecase, use_case_table[out->usecase], get_device_types(devices));
4651
4652 list_init(&new_devices);
4653 assign_devices(&new_devices, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004654
4655 lock_output_stream(out);
4656 pthread_mutex_lock(&adev->lock);
4657
4658 /*
4659 * When HDMI cable is unplugged the music playback is paused and
4660 * the policy manager sends routing=0. But the audioflinger continues
4661 * to write data until standby time (3sec). As the HDMI core is
4662 * turned off, the write gets blocked.
4663 * Avoid this by routing audio to speaker until standby.
4664 */
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08004665 if (is_single_device_type_equal(&out->device_list,
4666 AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004667 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004668 !audio_extn_passthru_is_passthrough_stream(out) &&
4669 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004670 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004671 }
4672 /*
4673 * When A2DP is disconnected the
4674 * music playback is paused and the policy manager sends routing=0
4675 * But the audioflinger continues to write data until standby time
4676 * (3sec). As BT is turned off, the write gets blocked.
4677 * Avoid this by routing audio to speaker until standby.
4678 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004679 if (is_a2dp_out_device_type(&out->device_list) &&
4680 list_empty(&new_devices) &&
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004681 !audio_extn_a2dp_source_is_ready() &&
4682 !adev->bt_sco_on) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004683 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004684 }
4685 /*
4686 * When USB headset is disconnected the music platback paused
4687 * and the policy manager send routing=0. But if the USB is connected
4688 * back before the standby time, AFE is not closed and opened
4689 * when USB is connected back. So routing to speker will guarantee
4690 * AFE reconfiguration and AFE will be opend once USB is connected again
4691 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004692 if (is_usb_out_device_type(&out->device_list) &&
4693 list_empty(&new_devices) &&
4694 !audio_extn_usb_connected(NULL)) {
4695 reassign_device_list(&new_devices, AUDIO_DEVICE_OUT_SPEAKER, "");
4696 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004697 /* To avoid a2dp to sco overlapping / BT device improper state
4698 * check with BT lib about a2dp streaming support before routing
4699 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004700 if (is_a2dp_out_device_type(&new_devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004701 if (!audio_extn_a2dp_source_is_ready()) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004702 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER) ||
4703 compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004704 //combo usecase just by pass a2dp
4705 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
4706 bypass_a2dp = true;
4707 } else {
4708 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4709 /* update device to a2dp and don't route as BT returned error
4710 * However it is still possible a2dp routing called because
4711 * of current active device disconnection (like wired headset)
4712 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004713 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004714 pthread_mutex_unlock(&adev->lock);
4715 pthread_mutex_unlock(&out->lock);
4716 goto error;
4717 }
4718 }
4719 }
4720
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004721 // Workaround: If routing to an non existing usb device, fail gracefully
4722 // The routing request will otherwise block during 10 second
4723 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004724 if (is_usb_out_device_type(&new_devices)) {
4725 struct str_parms *parms =
4726 str_parms_create_str(get_usb_device_address(&new_devices));
4727 if (!parms)
4728 goto error;
4729 if ((card = get_alive_usb_card(parms)) >= 0) {
4730 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
4731 pthread_mutex_unlock(&adev->lock);
4732 pthread_mutex_unlock(&out->lock);
4733 str_parms_destroy(parms);
4734 ret = -ENOSYS;
4735 goto error;
4736 }
4737 str_parms_destroy(parms);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004738 }
4739
Weiyin Jiang80c8f9a2020-01-10 20:42:08 +08004740 // Workaround: If routing to an non existing hdmi device, fail gracefully
4741 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4742 (platform_get_edid_info_v2(adev->platform,
4743 out->extconn.cs.controller,
4744 out->extconn.cs.stream) != 0)) {
4745 ALOGW("out_set_parameters() ignoring rerouting to non existing HDMI/DP");
4746 pthread_mutex_unlock(&adev->lock);
4747 pthread_mutex_unlock(&out->lock);
4748 ret = -ENOSYS;
4749 goto error;
4750 }
4751
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004752 /*
4753 * select_devices() call below switches all the usecases on the same
4754 * backend to the new device. Refer to check_usecases_codec_backend() in
4755 * the select_devices(). But how do we undo this?
4756 *
4757 * For example, music playback is active on headset (deep-buffer usecase)
4758 * and if we go to ringtones and select a ringtone, low-latency usecase
4759 * will be started on headset+speaker. As we can't enable headset+speaker
4760 * and headset devices at the same time, select_devices() switches the music
4761 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4762 * So when the ringtone playback is completed, how do we undo the same?
4763 *
4764 * We are relying on the out_set_parameters() call on deep-buffer output,
4765 * once the ringtone playback is ended.
4766 * NOTE: We should not check if the current devices are same as new devices.
4767 * Because select_devices() must be called to switch back the music
4768 * playback to headset.
4769 */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004770 if (!list_empty(&new_devices)) {
4771 bool same_dev = compare_devices(&out->device_list, &new_devices);
4772 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004773
4774 if (output_drives_call(adev, out)) {
4775 if (!voice_is_call_state_active(adev)) {
4776 if (adev->mode == AUDIO_MODE_IN_CALL) {
4777 adev->current_call_output = out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004778 if (is_usb_out_device_type(&out->device_list)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004779 service_interval =
4780 audio_extn_usb_find_service_interval(true, true /*playback*/);
4781 audio_extn_usb_set_service_interval(true /*playback*/,
4782 service_interval,
4783 &reconfig);
4784 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4785 }
4786 ret = voice_start_call(adev);
4787 }
4788 } else {
4789 adev->current_call_output = out;
4790 voice_update_devices_for_all_voice_usecases(adev);
4791 }
4792 }
4793
4794 if (!out->standby) {
4795 if (!same_dev) {
4796 ALOGV("update routing change");
4797 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4798 adev->perf_lock_opts,
4799 adev->perf_lock_opts_size);
4800 if (adev->adm_on_routing_change)
4801 adev->adm_on_routing_change(adev->adm_data,
4802 out->handle);
4803 }
4804 if (!bypass_a2dp) {
4805 select_devices(adev, out->usecase);
4806 } else {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004807 if (compare_device_type(&new_devices, AUDIO_DEVICE_OUT_SPEAKER_SAFE))
4808 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004809 else
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004810 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004811 select_devices(adev, out->usecase);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004812 assign_devices(&out->device_list, &new_devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004813 }
4814
4815 if (!same_dev) {
4816 // on device switch force swap, lower functions will make sure
4817 // to check if swap is allowed or not.
4818 platform_set_swap_channels(adev, true);
4819 audio_extn_perf_lock_release(&adev->perf_lock_handle);
4820 }
4821 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4822 out->a2dp_compress_mute &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004823 (!is_a2dp_out_device_type(&out->device_list) || audio_extn_a2dp_source_is_ready())) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004824 pthread_mutex_lock(&out->compr_mute_lock);
4825 out->a2dp_compress_mute = false;
4826 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4827 pthread_mutex_unlock(&out->compr_mute_lock);
4828 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4829 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
4830 }
4831 }
4832 }
4833
4834 pthread_mutex_unlock(&adev->lock);
4835 pthread_mutex_unlock(&out->lock);
4836
4837 /*handles device and call state changes*/
4838 audio_extn_extspk_update(adev->extspk);
4839
4840error:
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004841 ALOGV("%s: exit: code(%d)", __func__, ret);
4842 return ret;
4843}
4844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004845static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4846{
4847 struct stream_out *out = (struct stream_out *)stream;
4848 struct audio_device *adev = out->dev;
4849 struct str_parms *parms;
4850 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07004851 int ret = 0, err;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004852 int ext_controller = -1;
4853 int ext_stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004854
sangwoobc677242013-08-08 16:53:43 +09004855 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004856 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004857 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304858 if (!parms)
4859 goto error;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004860
4861 err = platform_get_controller_stream_from_params(parms, &ext_controller,
4862 &ext_stream);
4863 if (err >= 0) {
4864 out->extconn.cs.controller = ext_controller;
4865 out->extconn.cs.stream = ext_stream;
4866 ALOGD("%s: usecase(%s) new controller/stream (%d/%d)", __func__,
4867 use_case_table[out->usecase], out->extconn.cs.controller,
4868 out->extconn.cs.stream);
4869 }
4870
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004871 if (out == adev->primary_output) {
4872 pthread_mutex_lock(&adev->lock);
4873 audio_extn_set_parameters(adev, parms);
4874 pthread_mutex_unlock(&adev->lock);
4875 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004876 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004877 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004878 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004879
4880 audio_extn_dts_create_state_notifier_node(out->usecase);
4881 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4882 popcount(out->channel_mask),
4883 out->playback_started);
4884
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004885 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004886 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004887
Surendar Karkaf51b5842018-04-26 11:28:38 +05304888 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4889 sizeof(value));
4890 if (err >= 0) {
4891 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4892 audio_extn_send_dual_mono_mixing_coefficients(out);
4893 }
4894
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304895 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4896 if (err >= 0) {
4897 strlcpy(out->profile, value, sizeof(out->profile));
4898 ALOGV("updating stream profile with value '%s'", out->profile);
4899 lock_output_stream(out);
4900 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4901 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08004902 &out->device_list, out->flags,
4903 out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304904 out->sample_rate, out->bit_width,
4905 out->channel_mask, out->profile,
4906 &out->app_type_cfg);
4907 pthread_mutex_unlock(&out->lock);
4908 }
4909
Alexy Joseph98988832017-01-13 14:56:59 -08004910 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004911 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4912 // and vendor.audio.hal.output.suspend.supported is set to true
4913 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004914 //check suspend parameter only for low latency and if the property
4915 //is enabled
4916 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4917 ALOGI("%s: got suspend_playback %s", __func__, value);
4918 lock_output_stream(out);
4919 if (!strncmp(value, "false", 5)) {
4920 //suspend_playback=false is supposed to set QOS value back to 75%
4921 //the mixer control sent with value Enable will achieve that
4922 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4923 } else if (!strncmp (value, "true", 4)) {
4924 //suspend_playback=true is supposed to remove QOS value
4925 //resetting the mixer control will set the default value
4926 //for the mixer control which is Disable and this removes the QOS vote
4927 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4928 } else {
4929 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4930 " got %s", __func__, value);
4931 ret = -1;
4932 }
4933
4934 if (ret != 0) {
4935 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4936 __func__, out->pm_qos_mixer_path, ret);
4937 }
4938
4939 pthread_mutex_unlock(&out->lock);
4940 }
4941 }
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07004942
Alexy Joseph98988832017-01-13 14:56:59 -08004943 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004944 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304945error:
Eric Laurent994a6932013-07-17 11:51:42 -07004946 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004947 return ret;
4948}
4949
Paul McLeana50b7332018-12-17 08:24:21 -07004950static int in_set_microphone_direction(const struct audio_stream_in *stream,
4951 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004952 struct stream_in *in = (struct stream_in *)stream;
4953
4954 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4955
4956 in->direction = dir;
4957
4958 if (in->standby)
4959 return 0;
4960
4961 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004962}
4963
4964static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004965 struct stream_in *in = (struct stream_in *)stream;
4966
4967 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4968
4969 if (zoom > 1.0 || zoom < -1.0)
4970 return -EINVAL;
4971
4972 in->zoom = zoom;
4973
4974 if (in->standby)
4975 return 0;
4976
4977 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004978}
4979
4980
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004981static bool stream_get_parameter_channels(struct str_parms *query,
4982 struct str_parms *reply,
4983 audio_channel_mask_t *supported_channel_masks) {
4984 int ret = -1;
4985 char value[512];
4986 bool first = true;
4987 size_t i, j;
4988
4989 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4990 ret = 0;
4991 value[0] = '\0';
4992 i = 0;
4993 while (supported_channel_masks[i] != 0) {
4994 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4995 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4996 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304997 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004998
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304999 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005000 first = false;
5001 break;
5002 }
5003 }
5004 i++;
5005 }
5006 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5007 }
5008 return ret == 0;
5009}
5010
5011static bool stream_get_parameter_formats(struct str_parms *query,
5012 struct str_parms *reply,
5013 audio_format_t *supported_formats) {
5014 int ret = -1;
5015 char value[256];
5016 size_t i, j;
5017 bool first = true;
5018
5019 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
5020 ret = 0;
5021 value[0] = '\0';
5022 i = 0;
5023 while (supported_formats[i] != 0) {
5024 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5025 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
5026 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305027 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005028 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05305029 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005030 first = false;
5031 break;
5032 }
5033 }
5034 i++;
5035 }
5036 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
5037 }
5038 return ret == 0;
5039}
5040
5041static bool stream_get_parameter_rates(struct str_parms *query,
5042 struct str_parms *reply,
5043 uint32_t *supported_sample_rates) {
5044
5045 int i;
5046 char value[256];
5047 int ret = -1;
5048 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
5049 ret = 0;
5050 value[0] = '\0';
5051 i=0;
5052 int cursor = 0;
5053 while (supported_sample_rates[i]) {
5054 int avail = sizeof(value) - cursor;
5055 ret = snprintf(value + cursor, avail, "%s%d",
5056 cursor > 0 ? "|" : "",
5057 supported_sample_rates[i]);
5058 if (ret < 0 || ret >= avail) {
5059 // if cursor is at the last element of the array
5060 // overwrite with \0 is duplicate work as
5061 // snprintf already put a \0 in place.
5062 // else
5063 // we had space to write the '|' at value[cursor]
5064 // (which will be overwritten) or no space to fill
5065 // the first element (=> cursor == 0)
5066 value[cursor] = '\0';
5067 break;
5068 }
5069 cursor += ret;
5070 ++i;
5071 }
5072 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
5073 value);
5074 }
5075 return ret >= 0;
5076}
5077
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005078static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
5079{
5080 struct stream_out *out = (struct stream_out *)stream;
5081 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005082 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005083 char value[256];
5084 struct str_parms *reply = str_parms_create();
5085 size_t i, j;
5086 int ret;
5087 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005088
5089 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005090 if (reply) {
5091 str_parms_destroy(reply);
5092 }
5093 if (query) {
5094 str_parms_destroy(query);
5095 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07005096 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
5097 return NULL;
5098 }
5099
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005100 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005101 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
5102 if (ret >= 0) {
5103 value[0] = '\0';
5104 i = 0;
5105 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005106 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
5107 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005108 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005109 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005110 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005111 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005112 first = false;
5113 break;
5114 }
5115 }
5116 i++;
5117 }
5118 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
5119 str = str_parms_to_str(reply);
5120 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005121 voice_extn_out_get_parameters(out, query, reply);
5122 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005123 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005124
Alexy Joseph62142aa2015-11-16 15:10:34 -08005125
5126 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
5127 if (ret >= 0) {
5128 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05305129 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
5130 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08005131 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305132 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005133 } else {
5134 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05305135 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08005136 }
5137 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005138 if (str)
5139 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08005140 str = str_parms_to_str(reply);
5141 }
5142
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005143 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
5144 if (ret >= 0) {
5145 value[0] = '\0';
5146 i = 0;
5147 first = true;
5148 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005149 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
5150 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005151 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08005152 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005153 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005154 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005155 first = false;
5156 break;
5157 }
5158 }
5159 i++;
5160 }
5161 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08005162 if (str)
5163 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005164 str = str_parms_to_str(reply);
5165 }
Mingming Yin3a941d42016-02-17 18:08:05 -08005166
5167 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
5168 if (ret >= 0) {
5169 value[0] = '\0';
5170 i = 0;
5171 first = true;
5172 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005173 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
5174 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08005175 if (!first) {
5176 strlcat(value, "|", sizeof(value));
5177 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07005178 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08005179 first = false;
5180 break;
5181 }
5182 }
5183 i++;
5184 }
5185 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
5186 if (str)
5187 free(str);
5188 str = str_parms_to_str(reply);
5189 }
5190
Alexy Joseph98988832017-01-13 14:56:59 -08005191 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
5192 //only low latency track supports suspend_resume
5193 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08005194 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08005195 if (str)
5196 free(str);
5197 str = str_parms_to_str(reply);
5198 }
5199
5200
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005201 str_parms_destroy(query);
5202 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07005203 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005204 return str;
5205}
5206
5207static uint32_t out_get_latency(const struct audio_stream_out *stream)
5208{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005209 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005210 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08005211 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212
Alexy Josephaa54c872014-12-03 02:46:47 -08005213 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05305214 lock_output_stream(out);
5215 latency = audio_extn_utils_compress_get_dsp_latency(out);
5216 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005217 } else if ((out->realtime) ||
5218 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005219 // since the buffer won't be filled up faster than realtime,
5220 // return a smaller number
5221 if (out->config.rate)
5222 period_ms = (out->af_period_multiplier * out->config.period_size *
5223 1000) / (out->config.rate);
5224 else
5225 period_ms = 0;
5226 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005227 } else {
5228 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005229 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005230 }
5231
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005232 if (is_a2dp_out_device_type(&out->device_list))
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005233 latency += audio_extn_a2dp_get_encoder_latency();
5234
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305235 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005236 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005237}
5238
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305239static float AmpToDb(float amplification)
5240{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305241 float db = DSD_VOLUME_MIN_DB;
5242 if (amplification > 0) {
5243 db = 20 * log10(amplification);
5244 if(db < DSD_VOLUME_MIN_DB)
5245 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305246 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305247 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305248}
5249
Arun Mirpuri5d170872019-03-26 13:21:31 -07005250static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5251 float right)
5252{
5253 struct stream_out *out = (struct stream_out *)stream;
5254 long volume = 0;
5255 char mixer_ctl_name[128] = "";
5256 struct audio_device *adev = out->dev;
5257 struct mixer_ctl *ctl = NULL;
5258 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5259 PCM_PLAYBACK);
5260
5261 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5262 "Playback %d Volume", pcm_device_id);
5263 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5264 if (!ctl) {
5265 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5266 __func__, mixer_ctl_name);
5267 return -EINVAL;
5268 }
5269 if (left != right)
5270 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5271 __func__, left, right);
5272 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5273 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5274 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5275 __func__, mixer_ctl_name, volume);
5276 return -EINVAL;
5277 }
5278 return 0;
5279}
5280
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305281static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5282 float right)
5283{
5284 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305285 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305286 char mixer_ctl_name[128];
5287 struct audio_device *adev = out->dev;
5288 struct mixer_ctl *ctl;
5289 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5290 PCM_PLAYBACK);
5291
5292 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5293 "Compress Playback %d Volume", pcm_device_id);
5294 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5295 if (!ctl) {
5296 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5297 __func__, mixer_ctl_name);
5298 return -EINVAL;
5299 }
5300 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5301 __func__, mixer_ctl_name, left, right);
5302 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5303 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5304 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5305
5306 return 0;
5307}
5308
Zhou Song2b8f28f2017-09-11 10:51:38 +08005309static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5310 float right)
5311{
5312 struct stream_out *out = (struct stream_out *)stream;
5313 char mixer_ctl_name[] = "App Type Gain";
5314 struct audio_device *adev = out->dev;
5315 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305316 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005317
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005318 if (!is_valid_volume(left, right)) {
5319 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5320 __func__, left, right);
5321 return -EINVAL;
5322 }
5323
Zhou Song2b8f28f2017-09-11 10:51:38 +08005324 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5325 if (!ctl) {
5326 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5327 __func__, mixer_ctl_name);
5328 return -EINVAL;
5329 }
5330
5331 set_values[0] = 0; //0: Rx Session 1:Tx Session
5332 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305333 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5334 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005335
5336 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5337 return 0;
5338}
5339
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305340static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5341 float right)
5342{
5343 struct stream_out *out = (struct stream_out *)stream;
5344 /* Volume control for pcm playback */
5345 if (left != right) {
5346 return -EINVAL;
5347 } else {
5348 char mixer_ctl_name[128];
5349 struct audio_device *adev = out->dev;
5350 struct mixer_ctl *ctl;
5351 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5352 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5353 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5354 if (!ctl) {
5355 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5356 return -EINVAL;
5357 }
5358
5359 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5360 int ret = mixer_ctl_set_value(ctl, 0, volume);
5361 if (ret < 0) {
5362 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5363 return -EINVAL;
5364 }
5365
5366 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5367
5368 return 0;
5369 }
5370}
5371
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005372static int out_set_volume(struct audio_stream_out *stream, float left,
5373 float right)
5374{
Eric Laurenta9024de2013-04-04 09:19:12 -07005375 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005376 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305377 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005378
Arun Mirpuri5d170872019-03-26 13:21:31 -07005379 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005380 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5381 /* only take left channel into account: the API is for stereo anyway */
5382 out->muted = (left == 0.0f);
5383 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005384 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305385 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005386 /*
5387 * Set mute or umute on HDMI passthrough stream.
5388 * Only take left channel into account.
5389 * Mute is 0 and unmute 1
5390 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305391 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305392 } else if (out->format == AUDIO_FORMAT_DSD){
5393 char mixer_ctl_name[128] = "DSD Volume";
5394 struct audio_device *adev = out->dev;
5395 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5396
5397 if (!ctl) {
5398 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5399 __func__, mixer_ctl_name);
5400 return -EINVAL;
5401 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305402 volume[0] = (long)(AmpToDb(left));
5403 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305404 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5405 return 0;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005406 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS) &&
Derek Chendf05eea2019-08-01 13:57:49 -07005407 (out->car_audio_stream == CAR_AUDIO_STREAM_MEDIA)) {
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005408 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5409 struct listnode *node = NULL;
5410 list_for_each(node, &adev->active_outputs_list) {
5411 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5412 streams_output_ctxt_t,
5413 list);
5414 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5415 out->volume_l = out_ctxt->output->volume_l;
5416 out->volume_r = out_ctxt->output->volume_r;
5417 }
5418 }
5419 if (!out->a2dp_compress_mute) {
5420 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5421 }
5422 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005423 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305424 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005425 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305426 if (!out->a2dp_compress_mute)
5427 ret = out_set_compr_volume(stream, left, right);
5428 out->volume_l = left;
5429 out->volume_r = right;
5430 pthread_mutex_unlock(&out->compr_mute_lock);
5431 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005432 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005433 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005434 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5435 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5436 if (!out->standby) {
5437 audio_extn_utils_send_app_type_gain(out->dev,
5438 out->app_type_cfg.app_type,
5439 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005440 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005441 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005442 out->volume_l = left;
5443 out->volume_r = right;
5444 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005445 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5446 ALOGV("%s: MMAP set volume called", __func__);
5447 if (!out->standby)
5448 ret = out_set_mmap_volume(stream, left, right);
5449 out->volume_l = left;
5450 out->volume_r = right;
5451 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305452 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305453 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5454 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305455 /* Volume control for pcm playback */
5456 if (!out->standby)
5457 ret = out_set_pcm_volume(stream, left, right);
5458 else
5459 out->apply_volume = true;
5460
5461 out->volume_l = left;
5462 out->volume_r = right;
5463 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005464 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5465 ALOGV("%s: bus device set volume called", __func__);
5466 if (!out->standby)
5467 ret = out_set_pcm_volume(stream, left, right);
5468 out->volume_l = left;
5469 out->volume_r = right;
5470 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005471 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005472
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005473 return -ENOSYS;
5474}
5475
Zhou Songc9672822017-08-16 16:01:39 +08005476static void update_frames_written(struct stream_out *out, size_t bytes)
5477{
5478 size_t bpf = 0;
5479
5480 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5481 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5482 bpf = 1;
5483 else if (!is_offload_usecase(out->usecase))
5484 bpf = audio_bytes_per_sample(out->format) *
5485 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005486
5487 pthread_mutex_lock(&out->position_query_lock);
5488 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005489 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005490 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5491 }
5492 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005493}
5494
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005495int split_and_write_audio_haptic_data(struct stream_out *out,
5496 const void *buffer, size_t bytes_to_write)
5497{
5498 struct audio_device *adev = out->dev;
5499
5500 int ret = 0;
5501 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5502 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5503 size_t frame_size = channel_count * bytes_per_sample;
5504 size_t frame_count = bytes_to_write / frame_size;
5505
5506 bool force_haptic_path =
5507 property_get_bool("vendor.audio.test_haptic", false);
5508
5509 // extract Haptics data from Audio buffer
5510 bool alloc_haptic_buffer = false;
5511 int haptic_channel_count = adev->haptics_config.channels;
5512 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5513 size_t audio_frame_size = frame_size - haptic_frame_size;
5514 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5515
5516 if (adev->haptic_buffer == NULL) {
5517 alloc_haptic_buffer = true;
5518 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5519 free(adev->haptic_buffer);
5520 adev->haptic_buffer_size = 0;
5521 alloc_haptic_buffer = true;
5522 }
5523
5524 if (alloc_haptic_buffer) {
5525 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005526 if(adev->haptic_buffer == NULL) {
5527 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5528 return -ENOMEM;
5529 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005530 adev->haptic_buffer_size = total_haptic_buffer_size;
5531 }
5532
5533 size_t src_index = 0, aud_index = 0, hap_index = 0;
5534 uint8_t *audio_buffer = (uint8_t *)buffer;
5535 uint8_t *haptic_buffer = adev->haptic_buffer;
5536
5537 // This is required for testing only. This works for stereo data only.
5538 // One channel is fed to audio stream and other to haptic stream for testing.
5539 if (force_haptic_path)
5540 audio_frame_size = haptic_frame_size = bytes_per_sample;
5541
5542 for (size_t i = 0; i < frame_count; i++) {
5543 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5544 audio_frame_size);
5545 aud_index += audio_frame_size;
5546 src_index += audio_frame_size;
5547
5548 if (adev->haptic_pcm)
5549 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5550 haptic_frame_size);
5551 hap_index += haptic_frame_size;
5552 src_index += haptic_frame_size;
5553
5554 // This is required for testing only.
5555 // Discard haptic channel data.
5556 if (force_haptic_path)
5557 src_index += haptic_frame_size;
5558 }
5559
5560 // write to audio pipeline
5561 ret = pcm_write(out->pcm, (void *)audio_buffer,
5562 frame_count * audio_frame_size);
5563
5564 // write to haptics pipeline
5565 if (adev->haptic_pcm)
5566 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5567 frame_count * haptic_frame_size);
5568
5569 return ret;
5570}
5571
Aalique Grahame22e49102018-12-18 14:23:57 -08005572#ifdef NO_AUDIO_OUT
5573static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5574 const void *buffer __unused, size_t bytes)
5575{
5576 struct stream_out *out = (struct stream_out *)stream;
5577
5578 /* No Output device supported other than BT for playback.
5579 * Sleep for the amount of buffer duration
5580 */
5581 lock_output_stream(out);
5582 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5583 (const struct audio_stream_out *)&out->stream) /
5584 out_get_sample_rate(&out->stream.common));
5585 pthread_mutex_unlock(&out->lock);
5586 return bytes;
5587}
5588#endif
5589
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005590static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5591 size_t bytes)
5592{
5593 struct stream_out *out = (struct stream_out *)stream;
5594 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005595 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305596 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005597 const size_t frame_size = audio_stream_out_frame_size(stream);
5598 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305599 struct audio_usecase *usecase = NULL;
Meng Wang4c32fb42020-01-16 17:57:11 +08005600 uint32_t compr_passthr = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005601
Haynes Mathew George380745d2017-10-04 15:27:45 -07005602 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005603 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305604
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305605 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005606
Dhananjay Kumarac341582017-02-23 23:42:25 +05305607 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305608 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305609 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5610 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005611 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305612 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305613 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305614 ALOGD(" %s: sound card is not active/SSR state", __func__);
5615 ret= -EIO;
5616 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305617 }
5618 }
5619
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305620 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305621 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305622 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305623 goto exit;
5624 }
5625
Haynes Mathew George16081042017-05-31 17:16:49 -07005626 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5627 ret = -EINVAL;
5628 goto exit;
5629 }
5630
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005631 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305632 !out->is_iec61937_info_available) {
5633
5634 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5635 out->is_iec61937_info_available = true;
5636 } else if (audio_extn_passthru_is_enabled()) {
5637 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305638 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305639
5640 if((out->format == AUDIO_FORMAT_DTS) ||
5641 (out->format == AUDIO_FORMAT_DTS_HD)) {
5642 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5643 buffer, bytes);
5644 if (ret) {
5645 if (ret != -ENOSYS) {
5646 out->is_iec61937_info_available = false;
5647 ALOGD("iec61937 transmission info not yet updated retry");
5648 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305649 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305650 /* if stream has started and after that there is
5651 * stream config change (iec transmission config)
5652 * then trigger select_device to update backend configuration.
5653 */
5654 out->stream_config_changed = true;
5655 pthread_mutex_lock(&adev->lock);
5656 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305657 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005658 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305659 ret = -EINVAL;
5660 goto exit;
5661 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305662 pthread_mutex_unlock(&adev->lock);
5663 out->stream_config_changed = false;
5664 out->is_iec61937_info_available = true;
5665 }
5666 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305667
Meng Wang4c32fb42020-01-16 17:57:11 +08005668#ifdef AUDIO_GKI_ENABLED
5669 /* out->compr_config.codec->reserved[0] is for compr_passthr */
5670 compr_passthr = out->compr_config.codec->reserved[0];
5671#else
5672 compr_passthr = out->compr_config.codec->compr_passthr;
5673#endif
5674
Garmond Leung317cbf12017-09-13 16:20:50 -07005675 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Meng Wang4c32fb42020-01-16 17:57:11 +08005676 (compr_passthr == PASSTHROUGH) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305677 (out->is_iec61937_info_available == true)) {
5678 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5679 ret = -EINVAL;
5680 goto exit;
5681 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305682 }
5683 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305684
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005685 if (is_a2dp_out_device_type(&out->device_list) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005686 (audio_extn_a2dp_source_is_suspended())) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005687 if (!(compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER) ||
5688 compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305689 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305690 ret = -EIO;
5691 goto exit;
5692 }
5693 }
5694 }
5695
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005696 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005697 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005698 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005699 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5700 ret = voice_extn_compress_voip_start_output_stream(out);
5701 else
5702 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005703 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005704 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005705 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005706 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005707 goto exit;
5708 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305709 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005710 if (last_known_cal_step != -1) {
5711 ALOGD("%s: retry previous failed cal level set", __func__);
5712 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305713 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005714 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305715
5716 if ((out->is_iec61937_info_available == true) &&
5717 (audio_extn_passthru_is_passthrough_stream(out))&&
5718 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5719 ret = -EINVAL;
5720 goto exit;
5721 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305722 if (out->set_dual_mono)
5723 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005724 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005725
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08005726 if (adev->is_channel_status_set == false &&
5727 compare_device_type(&out->device_list,
5728 AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Alexy Josephb1379942016-01-29 15:49:38 -08005729 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305730 adev->is_channel_status_set = true;
5731 }
5732
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305733 if ((adev->use_old_pspd_mix_ctrl == true) &&
5734 (out->pspd_coeff_sent == false)) {
5735 /*
5736 * Need to resend pspd coefficients after stream started for
5737 * older kernel version as it does not save the coefficients
5738 * and also stream has to be started for coeff to apply.
5739 */
5740 usecase = get_usecase_from_list(adev, out->usecase);
5741 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305742 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305743 out->pspd_coeff_sent = true;
5744 }
5745 }
5746
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005747 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005748 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005749 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005750 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005751 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5752 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305753 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5754 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangd9b5a4e2019-07-18 17:24:21 +08005755 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305756 out->send_next_track_params = false;
5757 out->is_compr_metadata_avail = false;
5758 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005759 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305760 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305761 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005762
Ashish Jain83a6cc22016-06-28 14:34:17 +05305763 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305764 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305765 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305766 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005767 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305768 return -EINVAL;
5769 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305770 audio_format_t dst_format = out->hal_op_format;
5771 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305772
Dieter Luecking5d57def2018-09-07 14:23:37 +02005773 /* prevent division-by-zero */
5774 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5775 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5776 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5777 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305778 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005779 ATRACE_END();
5780 return -EINVAL;
5781 }
5782
Ashish Jainf1eaa582016-05-23 20:54:24 +05305783 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5784 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5785
Ashish Jain83a6cc22016-06-28 14:34:17 +05305786 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305787 dst_format,
5788 buffer,
5789 src_format,
5790 frames);
5791
Ashish Jain83a6cc22016-06-28 14:34:17 +05305792 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305793 bytes_to_write);
5794
5795 /*Convert written bytes in audio flinger format*/
5796 if (ret > 0)
5797 ret = ((ret * format_to_bitwidth_table[out->format]) /
5798 format_to_bitwidth_table[dst_format]);
5799 }
5800 } else
5801 ret = compress_write(out->compr, buffer, bytes);
5802
Zhou Songc9672822017-08-16 16:01:39 +08005803 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5804 update_frames_written(out, bytes);
5805
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305806 if (ret < 0)
5807 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005808 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305809 /*msg to cb thread only if non blocking write is enabled*/
5810 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305811 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005812 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305813 } else if (-ENETRESET == ret) {
5814 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305815 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305816 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305817 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005818 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305819 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005820 }
Ashish Jain5106d362016-05-11 19:23:33 +05305821
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305822 /* Call compr start only when non-zero bytes of data is there to be rendered */
5823 if (!out->playback_started && ret > 0) {
5824 int status = compress_start(out->compr);
5825 if (status < 0) {
5826 ret = status;
5827 ALOGE("%s: compr start failed with err %d", __func__, errno);
5828 goto exit;
5829 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005830 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005831 out->playback_started = 1;
5832 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005833
5834 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5835 popcount(out->channel_mask),
5836 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005837 }
5838 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005839 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005840 return ret;
5841 } else {
5842 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005843 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005844 if (out->muted)
5845 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005846 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5847 __func__, frames, frame_size, bytes_to_write);
5848
Aalique Grahame22e49102018-12-18 14:23:57 -08005849 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005850 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5851 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5852 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005853 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5854 int16_t *src = (int16_t *)buffer;
5855 int16_t *dst = (int16_t *)buffer;
5856
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005857 LOG_ALWAYS_FATAL_IF(channel_count > 2 ||
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005858 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005859 "out_write called for %s use case with wrong properties",
5860 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005861
5862 /*
5863 * FIXME: this can be removed once audio flinger mixer supports
5864 * mono output
5865 */
5866
5867 /*
5868 * Code below goes over each frame in the buffer and adds both
5869 * L and R samples and then divides by 2 to convert to mono
5870 */
Yunfei Zhanga6cd66d2019-07-22 16:15:36 +08005871 if (channel_count == 2) {
5872 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5873 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5874 }
5875 bytes_to_write /= 2;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005876 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005877 }
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305878 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005879
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005880 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005881
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005882 if (out->config.rate)
5883 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5884 out->config.rate;
5885
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005886 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005887 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5888
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005889 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005890 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005891 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305892 out->convert_buffer != NULL) {
5893
5894 memcpy_by_audio_format(out->convert_buffer,
5895 out->hal_op_format,
5896 buffer,
5897 out->hal_ip_format,
5898 out->config.period_size * out->config.channels);
5899
5900 ret = pcm_write(out->pcm, out->convert_buffer,
5901 (out->config.period_size *
5902 out->config.channels *
5903 format_to_bitwidth_table[out->hal_op_format]));
5904 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305905 /*
5906 * To avoid underrun in DSP when the application is not pumping
5907 * data at required rate, check for the no. of bytes and ignore
5908 * pcm_write if it is less than actual buffer size.
5909 * It is a work around to a change in compress VOIP driver.
5910 */
5911 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5912 bytes < (out->config.period_size * out->config.channels *
5913 audio_bytes_per_sample(out->format))) {
5914 size_t voip_buf_size =
5915 out->config.period_size * out->config.channels *
5916 audio_bytes_per_sample(out->format);
5917 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5918 __func__, bytes, voip_buf_size);
5919 usleep(((uint64_t)voip_buf_size - bytes) *
5920 1000000 / audio_stream_out_frame_size(stream) /
5921 out_get_sample_rate(&out->stream.common));
5922 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005923 } else {
5924 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5925 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5926 else
5927 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5928 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305929 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005930
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005931 release_out_focus(out);
5932
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305933 if (ret < 0)
5934 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005935 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305936 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005937 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005938 }
5939
5940exit:
Zhou Songc9672822017-08-16 16:01:39 +08005941 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305942 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305943 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305944 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005945 pthread_mutex_unlock(&out->lock);
5946
5947 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005948 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005949 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305950 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305951 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305952 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305953 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305954 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305955 out->standby = true;
5956 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305957 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005958 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5959 /* prevent division-by-zero */
5960 uint32_t stream_size = audio_stream_out_frame_size(stream);
5961 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005962
Dieter Luecking5d57def2018-09-07 14:23:37 +02005963 if ((stream_size == 0) || (srate == 0)) {
5964 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5965 ATRACE_END();
5966 return -EINVAL;
5967 }
5968 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5969 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005970 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305971 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005972 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005973 return ret;
5974 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005975 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005976 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005977 return bytes;
5978}
5979
5980static int out_get_render_position(const struct audio_stream_out *stream,
5981 uint32_t *dsp_frames)
5982{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005983 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005984
5985 if (dsp_frames == NULL)
5986 return -EINVAL;
5987
5988 *dsp_frames = 0;
5989 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005990 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305991
5992 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5993 * this operation and adev_close_output_stream(where out gets reset).
5994 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305995 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005996 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305997 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005998 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305999 return 0;
6000 }
6001
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006002 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05306003 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306004 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006005 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05306006 if (ret < 0)
6007 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006008 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05306009 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006010 }
Naresh Tanniru80659832014-06-04 18:17:56 +05306011 if (-ENETRESET == ret) {
6012 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306013 out->card_status = CARD_STATUS_OFFLINE;
6014 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306015 } else if(ret < 0) {
6016 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306017 ret = -EINVAL;
6018 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05306019 /*
6020 * Handle corner case where compress session is closed during SSR
6021 * and timestamp is queried
6022 */
6023 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306024 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306025 } else if (out->prev_card_status_offline) {
6026 ALOGE("ERROR: previously sound card was offline,return error");
6027 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306028 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306029 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006030 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05306031 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306032 pthread_mutex_unlock(&out->lock);
6033 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08006034 } else if (audio_is_linear_pcm(out->format)) {
6035 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07006036 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08006037 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006038 } else
6039 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006040}
6041
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006042static int out_add_audio_effect(const struct audio_stream *stream __unused,
6043 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006044{
6045 return 0;
6046}
6047
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006048static int out_remove_audio_effect(const struct audio_stream *stream __unused,
6049 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006050{
6051 return 0;
6052}
6053
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006054static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
6055 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006056{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05306057 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006058}
6059
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006060static int out_get_presentation_position(const struct audio_stream_out *stream,
6061 uint64_t *frames, struct timespec *timestamp)
6062{
6063 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05306064 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07006065 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006066
Ashish Jain5106d362016-05-11 19:23:33 +05306067 /* below piece of code is not guarded against any lock because audioFliner serializes
6068 * this operation and adev_close_output_stream( where out gets reset).
6069 */
6070 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05306071 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08006072 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05306073 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
6074 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
6075 return 0;
6076 }
6077
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006078 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006079
Ashish Jain5106d362016-05-11 19:23:33 +05306080 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
6081 ret = compress_get_tstamp(out->compr, &dsp_frames,
6082 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08006083 // Adjustment accounts for A2dp encoder latency with offload usecases
6084 // Note: Encoder latency is returned in ms.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006085 if (is_a2dp_out_device_type(&out->device_list)) {
yidongh0515e042017-07-06 15:00:34 +08006086 unsigned long offset =
6087 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
6088 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
6089 }
Ashish Jain5106d362016-05-11 19:23:33 +05306090 ALOGVV("%s rendered frames %ld sample_rate %d",
6091 __func__, dsp_frames, out->sample_rate);
6092 *frames = dsp_frames;
6093 if (ret < 0)
6094 ret = -errno;
6095 if (-ENETRESET == ret) {
6096 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306097 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05306098 ret = -EINVAL;
6099 } else
6100 ret = 0;
6101 /* this is the best we can do */
6102 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07006103 } else {
6104 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08006105 unsigned int avail;
6106 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
6107 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
George Gao62ebc722019-07-29 16:29:44 -07006108
6109 uint64_t signed_frames = 0;
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006110 uint64_t frames_temp = 0;
George Gao62ebc722019-07-29 16:29:44 -07006111
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006112 frames_temp = (kernel_buffer_size > avail) ? (kernel_buffer_size - avail) : 0;
6113 if (out->written >= frames_temp)
6114 signed_frames = out->written - frames_temp;
George Gao62ebc722019-07-29 16:29:44 -07006115
Weiyin Jiangd4633762018-03-16 12:05:03 +08006116 // This adjustment accounts for buffering after app processor.
6117 // It is based on estimated DSP latency per use case, rather than exact.
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006118 frames_temp = platform_render_latency(out->usecase) * out->sample_rate / 1000000LL;
6119 if (signed_frames >= frames_temp)
6120 signed_frames -= frames_temp;
Aniket Kumar Lataff613152017-07-18 18:19:21 -07006121
Weiyin Jiangd4633762018-03-16 12:05:03 +08006122 // Adjustment accounts for A2dp encoder latency with non offload usecases
6123 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006124 if (is_a2dp_out_device_type(&out->device_list)) {
Weiyin Jiang0d25bcf2019-08-30 15:27:23 +08006125 frames_temp = audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000;
6126 if (signed_frames >= frames_temp)
6127 signed_frames -= frames_temp;
Weiyin Jiangd4633762018-03-16 12:05:03 +08006128 }
6129
6130 // It would be unusual for this value to be negative, but check just in case ...
George Gao62ebc722019-07-29 16:29:44 -07006131 *frames = signed_frames;
6132 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006133 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306134 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05306135 *frames = out->written;
6136 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306137 if (is_offload_usecase(out->usecase))
6138 ret = -EINVAL;
6139 else
6140 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006141 }
6142 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006143 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07006144 return ret;
6145}
6146
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006147static int out_set_callback(struct audio_stream_out *stream,
6148 stream_callback_t callback, void *cookie)
6149{
6150 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006151 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006152
6153 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006154 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006155 out->client_callback = callback;
6156 out->client_cookie = cookie;
6157 if (out->adsp_hdlr_stream_handle) {
6158 ret = audio_extn_adsp_hdlr_stream_set_callback(
6159 out->adsp_hdlr_stream_handle,
6160 callback,
6161 cookie);
6162 if (ret)
6163 ALOGW("%s:adsp hdlr callback registration failed %d",
6164 __func__, ret);
6165 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006166 pthread_mutex_unlock(&out->lock);
6167 return 0;
6168}
6169
6170static int out_pause(struct audio_stream_out* stream)
6171{
6172 struct stream_out *out = (struct stream_out *)stream;
6173 int status = -ENOSYS;
6174 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006175 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006176 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006177 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006178 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306179 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05306180 status = compress_pause(out->compr);
6181
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006182 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006183
Mingming Yin21854652016-04-13 11:54:02 -07006184 if (audio_extn_passthru_is_active()) {
6185 ALOGV("offload use case, pause passthru");
6186 audio_extn_passthru_on_pause(out);
6187 }
6188
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306189 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006190 audio_extn_dts_notify_playback_state(out->usecase, 0,
6191 out->sample_rate, popcount(out->channel_mask),
6192 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006193 }
6194 pthread_mutex_unlock(&out->lock);
6195 }
6196 return status;
6197}
6198
6199static int out_resume(struct audio_stream_out* stream)
6200{
6201 struct stream_out *out = (struct stream_out *)stream;
6202 int status = -ENOSYS;
6203 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006204 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006205 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006206 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006207 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006208 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306209 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05306210 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07006211 }
6212 if (!status) {
6213 out->offload_state = OFFLOAD_STATE_PLAYING;
6214 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05306215 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08006216 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
6217 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006218 }
6219 pthread_mutex_unlock(&out->lock);
6220 }
6221 return status;
6222}
6223
6224static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
6225{
6226 struct stream_out *out = (struct stream_out *)stream;
6227 int status = -ENOSYS;
6228 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006229 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006230 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006231 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
6232 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
6233 else
6234 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
6235 pthread_mutex_unlock(&out->lock);
6236 }
6237 return status;
6238}
6239
6240static int out_flush(struct audio_stream_out* stream)
6241{
6242 struct stream_out *out = (struct stream_out *)stream;
6243 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006244 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006245 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006246 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006247 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6248 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006249 } else {
6250 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6251 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006252 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006253 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006254 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006255 return 0;
6256 }
6257 return -ENOSYS;
6258}
6259
Haynes Mathew George16081042017-05-31 17:16:49 -07006260static int out_stop(const struct audio_stream_out* stream)
6261{
6262 struct stream_out *out = (struct stream_out *)stream;
6263 struct audio_device *adev = out->dev;
6264 int ret = -ENOSYS;
6265
6266 ALOGV("%s", __func__);
6267 pthread_mutex_lock(&adev->lock);
6268 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6269 out->playback_started && out->pcm != NULL) {
6270 pcm_stop(out->pcm);
6271 ret = stop_output_stream(out);
6272 out->playback_started = false;
6273 }
6274 pthread_mutex_unlock(&adev->lock);
6275 return ret;
6276}
6277
6278static int out_start(const struct audio_stream_out* stream)
6279{
6280 struct stream_out *out = (struct stream_out *)stream;
6281 struct audio_device *adev = out->dev;
6282 int ret = -ENOSYS;
6283
6284 ALOGV("%s", __func__);
6285 pthread_mutex_lock(&adev->lock);
6286 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6287 !out->playback_started && out->pcm != NULL) {
6288 ret = start_output_stream(out);
6289 if (ret == 0) {
6290 out->playback_started = true;
6291 }
6292 }
6293 pthread_mutex_unlock(&adev->lock);
6294 return ret;
6295}
6296
6297/*
6298 * Modify config->period_count based on min_size_frames
6299 */
6300static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6301{
6302 int periodCountRequested = (min_size_frames + config->period_size - 1)
6303 / config->period_size;
6304 int periodCount = MMAP_PERIOD_COUNT_MIN;
6305
6306 ALOGV("%s original config.period_size = %d config.period_count = %d",
6307 __func__, config->period_size, config->period_count);
6308
6309 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6310 periodCount *= 2;
6311 }
6312 config->period_count = periodCount;
6313
6314 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6315}
6316
Phil Burkfe17efd2019-03-25 10:23:35 -07006317// Read offset for the positional timestamp from a persistent vendor property.
6318// This is to workaround apparent inaccuracies in the timing information that
6319// is used by the AAudio timing model. The inaccuracies can cause glitches.
6320static int64_t get_mmap_out_time_offset() {
6321 const int32_t kDefaultOffsetMicros = 0;
6322 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006323 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006324 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6325 return mmap_time_offset_micros * (int64_t)1000;
6326}
6327
Haynes Mathew George16081042017-05-31 17:16:49 -07006328static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6329 int32_t min_size_frames,
6330 struct audio_mmap_buffer_info *info)
6331{
6332 struct stream_out *out = (struct stream_out *)stream;
6333 struct audio_device *adev = out->dev;
6334 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006335 unsigned int offset1 = 0;
6336 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006337 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006338 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006339 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006340
Arun Mirpuri5d170872019-03-26 13:21:31 -07006341 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306342 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006343 pthread_mutex_lock(&adev->lock);
6344
Sharad Sanglec6f32552018-05-04 16:15:38 +05306345 if (CARD_STATUS_OFFLINE == out->card_status ||
6346 CARD_STATUS_OFFLINE == adev->card_status) {
6347 ALOGW("out->card_status or adev->card_status offline, try again");
6348 ret = -EIO;
6349 goto exit;
6350 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006351 if (info == NULL || min_size_frames == 0) {
6352 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6353 ret = -EINVAL;
6354 goto exit;
6355 }
6356 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6357 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6358 ret = -ENOSYS;
6359 goto exit;
6360 }
6361 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6362 if (out->pcm_device_id < 0) {
6363 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6364 __func__, out->pcm_device_id, out->usecase);
6365 ret = -EINVAL;
6366 goto exit;
6367 }
6368
6369 adjust_mmap_period_count(&out->config, min_size_frames);
6370
Arun Mirpuri5d170872019-03-26 13:21:31 -07006371 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006372 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6373 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6374 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306375 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306376 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6377 out->card_status = CARD_STATUS_OFFLINE;
6378 adev->card_status = CARD_STATUS_OFFLINE;
6379 ret = -EIO;
6380 goto exit;
6381 }
6382
Haynes Mathew George16081042017-05-31 17:16:49 -07006383 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6384 step = "open";
6385 ret = -ENODEV;
6386 goto exit;
6387 }
6388 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6389 if (ret < 0) {
6390 step = "begin";
6391 goto exit;
6392 }
6393 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006394 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006395 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006396 ret = platform_get_mmap_data_fd(adev->platform,
6397 out->pcm_device_id, 0 /*playback*/,
6398 &info->shared_memory_fd,
6399 &mmap_size);
6400 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006401 // Fall back to non exclusive mode
6402 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6403 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07006404 out->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
6405 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, out->mmap_shared_memory_fd);
6406
Arun Mirpuri5d170872019-03-26 13:21:31 -07006407 if (mmap_size < buffer_size) {
6408 step = "mmap";
6409 goto exit;
6410 }
6411 // FIXME: indicate exclusive mode support by returning a negative buffer size
6412 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006413 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006414 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006415 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006416
6417 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6418 if (ret < 0) {
6419 step = "commit";
6420 goto exit;
6421 }
6422
Phil Burkfe17efd2019-03-25 10:23:35 -07006423 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6424
Haynes Mathew George16081042017-05-31 17:16:49 -07006425 out->standby = false;
6426 ret = 0;
6427
Arun Mirpuri5d170872019-03-26 13:21:31 -07006428 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006429 __func__, info->shared_memory_address, info->buffer_size_frames);
6430
6431exit:
6432 if (ret != 0) {
6433 if (out->pcm == NULL) {
6434 ALOGE("%s: %s - %d", __func__, step, ret);
6435 } else {
6436 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6437 pcm_close(out->pcm);
6438 out->pcm = NULL;
6439 }
6440 }
6441 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306442 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006443 return ret;
6444}
6445
6446static int out_get_mmap_position(const struct audio_stream_out *stream,
6447 struct audio_mmap_position *position)
6448{
6449 struct stream_out *out = (struct stream_out *)stream;
6450 ALOGVV("%s", __func__);
6451 if (position == NULL) {
6452 return -EINVAL;
6453 }
6454 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006455 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006456 return -ENOSYS;
6457 }
6458 if (out->pcm == NULL) {
6459 return -ENOSYS;
6460 }
6461
6462 struct timespec ts = { 0, 0 };
6463 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6464 if (ret < 0) {
6465 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6466 return ret;
6467 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006468 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6469 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006470 return 0;
6471}
6472
6473
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006474/** audio_stream_in implementation **/
6475static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6476{
6477 struct stream_in *in = (struct stream_in *)stream;
6478
6479 return in->config.rate;
6480}
6481
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006482static int in_set_sample_rate(struct audio_stream *stream __unused,
6483 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006484{
6485 return -ENOSYS;
6486}
6487
6488static size_t in_get_buffer_size(const struct audio_stream *stream)
6489{
6490 struct stream_in *in = (struct stream_in *)stream;
6491
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006492 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6493 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006494 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6495 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306496 else if(audio_extn_cin_attached_usecase(in->usecase))
6497 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006498
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006499 return in->config.period_size * in->af_period_multiplier *
6500 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006501}
6502
6503static uint32_t in_get_channels(const struct audio_stream *stream)
6504{
6505 struct stream_in *in = (struct stream_in *)stream;
6506
6507 return in->channel_mask;
6508}
6509
6510static audio_format_t in_get_format(const struct audio_stream *stream)
6511{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006512 struct stream_in *in = (struct stream_in *)stream;
6513
6514 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006515}
6516
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006517static int in_set_format(struct audio_stream *stream __unused,
6518 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006519{
6520 return -ENOSYS;
6521}
6522
6523static int in_standby(struct audio_stream *stream)
6524{
6525 struct stream_in *in = (struct stream_in *)stream;
6526 struct audio_device *adev = in->dev;
6527 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306528 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6529 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006530 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306531
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006532 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006533 if (!in->standby && in->is_st_session) {
6534 ALOGD("%s: sound trigger pcm stop lab", __func__);
6535 audio_extn_sound_trigger_stop_lab(in);
George Gao3018ede2019-10-23 13:23:00 -07006536 if (adev->num_va_sessions > 0)
6537 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006538 in->standby = 1;
6539 }
6540
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006541 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006542 if (adev->adm_deregister_stream)
6543 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6544
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006545 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006546 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006547 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006548 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006549 voice_extn_compress_voip_close_input_stream(stream);
6550 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006551 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6552 do_stop = in->capture_started;
6553 in->capture_started = false;
Phil Burkd898ba62019-06-20 12:49:01 -07006554 if (in->mmap_shared_memory_fd >= 0) {
6555 ALOGV("%s: closing mmap_shared_memory_fd = %d",
6556 __func__, in->mmap_shared_memory_fd);
6557 close(in->mmap_shared_memory_fd);
6558 in->mmap_shared_memory_fd = -1;
6559 }
Zhou Songa8895042016-07-05 17:54:22 +08006560 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306561 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05306562 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006563 }
6564
Arun Mirpuri5d170872019-03-26 13:21:31 -07006565 if (in->pcm) {
6566 ATRACE_BEGIN("pcm_in_close");
6567 pcm_close(in->pcm);
6568 ATRACE_END();
6569 in->pcm = NULL;
6570 }
6571
Carter Hsu2e429db2019-05-14 18:50:52 +08006572 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006573 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006574
George Gao3018ede2019-10-23 13:23:00 -07006575 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6576 if (adev->num_va_sessions > 0)
6577 adev->num_va_sessions--;
6578 }
Quinn Malef6050362019-01-30 15:55:40 -08006579
Eric Laurent150dbfe2013-02-27 14:31:02 -08006580 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006581 }
6582 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006583 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006584 return status;
6585}
6586
Aalique Grahame22e49102018-12-18 14:23:57 -08006587static int in_dump(const struct audio_stream *stream,
6588 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006589{
Aalique Grahame22e49102018-12-18 14:23:57 -08006590 struct stream_in *in = (struct stream_in *)stream;
6591
6592 // We try to get the lock for consistency,
6593 // but it isn't necessary for these variables.
6594 // If we're not in standby, we may be blocked on a read.
6595 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6596 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6597 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6598 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6599
6600 if (locked) {
6601 pthread_mutex_unlock(&in->lock);
6602 }
6603
6604 // dump error info
6605 (void)error_log_dump(
6606 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6607
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006608 return 0;
6609}
6610
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306611static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6612{
6613 if (!stream || !parms)
6614 return;
6615
6616 struct stream_in *in = (struct stream_in *)stream;
6617 struct audio_device *adev = in->dev;
6618
6619 card_status_t status;
6620 int card;
6621 if (parse_snd_card_status(parms, &card, &status) < 0)
6622 return;
6623
6624 pthread_mutex_lock(&adev->lock);
6625 bool valid_cb = (card == adev->snd_card);
6626 pthread_mutex_unlock(&adev->lock);
6627
6628 if (!valid_cb)
6629 return;
6630
6631 lock_input_stream(in);
6632 if (in->card_status != status)
6633 in->card_status = status;
6634 pthread_mutex_unlock(&in->lock);
6635
6636 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6637 use_case_table[in->usecase],
6638 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6639
6640 // a better solution would be to report error back to AF and let
6641 // it put the stream to standby
6642 if (status == CARD_STATUS_OFFLINE)
6643 in_standby(&in->stream.common);
6644
6645 return;
6646}
6647
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006648int route_input_stream(struct stream_in *in,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006649 struct listnode *devices,
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006650 audio_source_t source)
6651{
6652 struct audio_device *adev = in->dev;
6653 int ret = 0;
6654
6655 lock_input_stream(in);
6656 pthread_mutex_lock(&adev->lock);
6657
6658 /* no audio source uses val == 0 */
6659 if ((in->source != source) && (source != AUDIO_SOURCE_DEFAULT)) {
6660 in->source = source;
6661 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6662 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6663 (voice_extn_compress_voip_is_format_supported(in->format)) &&
6664 (in->config.rate == 8000 || in->config.rate == 16000 ||
6665 in->config.rate == 32000 || in->config.rate == 48000 ) &&
6666 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
6667 ret = voice_extn_compress_voip_open_input_stream(in);
6668 if (ret != 0) {
6669 ALOGE("%s: Compress voip input cannot be opened, error:%d",
6670 __func__, ret);
6671 }
6672 }
6673 }
6674
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006675 if (!compare_devices(&in->device_list, devices) && !list_empty(devices) &&
6676 is_audio_in_device_type(devices)) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006677 // Workaround: If routing to an non existing usb device, fail gracefully
6678 // The routing request will otherwise block during 10 second
6679 int card;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006680 struct str_parms *usb_addr =
6681 str_parms_create_str(get_usb_device_address(devices));
6682 if (is_usb_in_device_type(devices) && usb_addr &&
6683 (card = get_alive_usb_card(usb_addr)) >= 0) {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006684 ALOGW("%s: ignoring rerouting to non existing USB card %d", __func__, card);
6685 ret = -ENOSYS;
6686 } else {
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006687 /* If recording is in progress, change the tx device to new device */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006688 assign_devices(&in->device_list, devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006689 if (!in->standby && !in->is_st_session) {
6690 ALOGV("update input routing change");
6691 // inform adm before actual routing to prevent glitches.
6692 if (adev->adm_on_routing_change) {
6693 adev->adm_on_routing_change(adev->adm_data,
6694 in->capture_handle);
6695 ret = select_devices(adev, in->usecase);
6696 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6697 adev->adm_routing_changed = true;
6698 }
6699 }
6700 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006701 if (usb_addr)
6702 str_parms_destroy(usb_addr);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006703 }
6704 pthread_mutex_unlock(&adev->lock);
6705 pthread_mutex_unlock(&in->lock);
6706
6707 ALOGD("%s: exit: status(%d)", __func__, ret);
6708 return ret;
6709}
6710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6712{
6713 struct stream_in *in = (struct stream_in *)stream;
6714 struct audio_device *adev = in->dev;
6715 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006716 char value[32];
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006717 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006718
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306719 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006720 parms = str_parms_create_str(kvpairs);
6721
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306722 if (!parms)
6723 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006724 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006725 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006726
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07006727 ret = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6728 if (ret >= 0) {
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306729 strlcpy(in->profile, value, sizeof(in->profile));
6730 ALOGV("updating stream profile with value '%s'", in->profile);
6731 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6732 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08006733 &in->device_list, in->flags, in->format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306734 in->sample_rate, in->bit_width,
6735 in->profile, &in->app_type_cfg);
6736 }
6737
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006738 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006739 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006740
6741 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306742error:
Eric Laurent994a6932013-07-17 11:51:42 -07006743 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006744 return ret;
6745}
6746
6747static char* in_get_parameters(const struct audio_stream *stream,
6748 const char *keys)
6749{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006750 struct stream_in *in = (struct stream_in *)stream;
6751 struct str_parms *query = str_parms_create_str(keys);
6752 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006753 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006754
6755 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006756 if (reply) {
6757 str_parms_destroy(reply);
6758 }
6759 if (query) {
6760 str_parms_destroy(query);
6761 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006762 ALOGE("in_get_parameters: failed to create query or reply");
6763 return NULL;
6764 }
6765
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006766 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006767
6768 voice_extn_in_get_parameters(in, query, reply);
6769
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006770 stream_get_parameter_channels(query, reply,
6771 &in->supported_channel_masks[0]);
6772 stream_get_parameter_formats(query, reply,
6773 &in->supported_formats[0]);
6774 stream_get_parameter_rates(query, reply,
6775 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006776 str = str_parms_to_str(reply);
6777 str_parms_destroy(query);
6778 str_parms_destroy(reply);
6779
6780 ALOGV("%s: exit: returns - %s", __func__, str);
6781 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006782}
6783
Aalique Grahame22e49102018-12-18 14:23:57 -08006784static int in_set_gain(struct audio_stream_in *stream,
6785 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006786{
Aalique Grahame22e49102018-12-18 14:23:57 -08006787 struct stream_in *in = (struct stream_in *)stream;
6788 char mixer_ctl_name[128];
6789 struct mixer_ctl *ctl;
6790 int ctl_value;
6791
6792 ALOGV("%s: gain %f", __func__, gain);
6793
6794 if (stream == NULL)
6795 return -EINVAL;
6796
6797 /* in_set_gain() only used to silence MMAP capture for now */
6798 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6799 return -ENOSYS;
6800
6801 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6802
6803 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6804 if (!ctl) {
6805 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6806 __func__, mixer_ctl_name);
6807 return -ENOSYS;
6808 }
6809
6810 if (gain < RECORD_GAIN_MIN)
6811 gain = RECORD_GAIN_MIN;
6812 else if (gain > RECORD_GAIN_MAX)
6813 gain = RECORD_GAIN_MAX;
6814 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6815
6816 mixer_ctl_set_value(ctl, 0, ctl_value);
6817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006818 return 0;
6819}
6820
6821static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6822 size_t bytes)
6823{
6824 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306825
6826 if (in == NULL) {
6827 ALOGE("%s: stream_in ptr is NULL", __func__);
6828 return -EINVAL;
6829 }
6830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006831 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306832 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306833 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006834
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006835 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306836
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006837 if (in->is_st_session) {
6838 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6839 /* Read from sound trigger HAL */
6840 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006841 if (in->standby) {
George Gao3018ede2019-10-23 13:23:00 -07006842 if (adev->num_va_sessions < UINT_MAX)
6843 adev->num_va_sessions++;
Quinn Malef6050362019-01-30 15:55:40 -08006844 in->standby = 0;
6845 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006846 pthread_mutex_unlock(&in->lock);
6847 return bytes;
6848 }
6849
Haynes Mathew George16081042017-05-31 17:16:49 -07006850 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6851 ret = -ENOSYS;
6852 goto exit;
6853 }
6854
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006855 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6856 !in->standby && adev->adm_routing_changed) {
6857 ret = -ENOSYS;
6858 goto exit;
6859 }
6860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006861 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006862 pthread_mutex_lock(&adev->lock);
6863 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6864 ret = voice_extn_compress_voip_start_input_stream(in);
6865 else
6866 ret = start_input_stream(in);
George Gao3018ede2019-10-23 13:23:00 -07006867 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION) {
6868 if (adev->num_va_sessions < UINT_MAX)
6869 adev->num_va_sessions++;
6870 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006871 pthread_mutex_unlock(&adev->lock);
6872 if (ret != 0) {
6873 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006874 }
6875 in->standby = 0;
6876 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006877
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306878 /* Avoid read if capture_stopped is set */
6879 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6880 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6881 ret = -EINVAL;
6882 goto exit;
6883 }
6884
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006885 // what's the duration requested by the client?
6886 long ns = 0;
6887
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306888 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006889 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6890 in->config.rate;
6891
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006892 ret = request_in_focus(in, ns);
6893 if (ret != 0)
6894 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006895 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006896
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306897 if (audio_extn_cin_attached_usecase(in->usecase)) {
6898 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6899 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306900 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006901 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306902 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006903 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006904 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006905 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006906 } else if (audio_extn_ffv_get_stream() == in) {
6907 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306908 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006909 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306910 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6911 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6912 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6913 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306914 ret = -EINVAL;
6915 goto exit;
6916 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306917 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306918 ret = -errno;
6919 }
6920 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306921 /* bytes read is always set to bytes for non compress usecases */
6922 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006923 }
6924
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006925 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006927 /*
Quinn Malef6050362019-01-30 15:55:40 -08006928 * Instead of writing zeroes here, we could trust the hardware to always
6929 * provide zeroes when muted. This is also muted with voice recognition
6930 * usecases so that other clients do not have access to voice recognition
6931 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006932 */
Quinn Malef6050362019-01-30 15:55:40 -08006933 if ((ret == 0 && voice_get_mic_mute(adev) &&
6934 !voice_is_in_call_rec_stream(in) &&
6935 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6936 (adev->num_va_sessions &&
6937 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6938 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6939 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006940 memset(buffer, 0, bytes);
6941
6942exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306943 frame_size = audio_stream_in_frame_size(stream);
6944 if (frame_size > 0)
6945 in->frames_read += bytes_read/frame_size;
6946
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006947 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306948 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006949 pthread_mutex_unlock(&in->lock);
6950
6951 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306952 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306953 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306954 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306955 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306956 in->standby = true;
6957 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306958 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6959 bytes_read = bytes;
6960 memset(buffer, 0, bytes);
6961 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006962 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006963 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6964 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006965 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306966 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306967 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006968 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306969 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006970}
6971
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006972static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006973{
6974 return 0;
6975}
6976
Aalique Grahame22e49102018-12-18 14:23:57 -08006977static int in_get_capture_position(const struct audio_stream_in *stream,
6978 int64_t *frames, int64_t *time)
6979{
6980 if (stream == NULL || frames == NULL || time == NULL) {
6981 return -EINVAL;
6982 }
6983 struct stream_in *in = (struct stream_in *)stream;
6984 int ret = -ENOSYS;
6985
6986 lock_input_stream(in);
6987 // note: ST sessions do not close the alsa pcm driver synchronously
6988 // on standby. Therefore, we may return an error even though the
6989 // pcm stream is still opened.
6990 if (in->standby) {
6991 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6992 "%s stream in standby but pcm not NULL for non ST session", __func__);
6993 goto exit;
6994 }
6995 if (in->pcm) {
6996 struct timespec timestamp;
6997 unsigned int avail;
6998 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6999 *frames = in->frames_read + avail;
7000 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
7001 ret = 0;
7002 }
7003 }
7004exit:
7005 pthread_mutex_unlock(&in->lock);
7006 return ret;
7007}
7008
Carter Hsu2e429db2019-05-14 18:50:52 +08007009static int in_update_effect_list(bool add, effect_handle_t effect,
7010 struct listnode *head)
7011{
7012 struct listnode *node;
7013 struct in_effect_list *elist = NULL;
7014 struct in_effect_list *target = NULL;
7015 int ret = 0;
7016
7017 if (!head)
7018 return ret;
7019
7020 list_for_each(node, head) {
7021 elist = node_to_item(node, struct in_effect_list, list);
7022 if (elist->handle == effect) {
7023 target = elist;
7024 break;
7025 }
7026 }
7027
7028 if (add) {
7029 if (target) {
7030 ALOGD("effect %p already exist", effect);
7031 return ret;
7032 }
7033
7034 target = (struct in_effect_list *)
7035 calloc(1, sizeof(struct in_effect_list));
7036
7037 if (!target) {
7038 ALOGE("%s:fail to allocate memory", __func__);
7039 return -ENOMEM;
7040 }
7041
7042 target->handle = effect;
7043 list_add_tail(head, &target->list);
7044 } else {
7045 if (target) {
7046 list_remove(&target->list);
7047 free(target);
7048 }
7049 }
7050
7051 return ret;
7052}
7053
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007054static int add_remove_audio_effect(const struct audio_stream *stream,
7055 effect_handle_t effect,
7056 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007057{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007058 struct stream_in *in = (struct stream_in *)stream;
7059 int status = 0;
7060 effect_descriptor_t desc;
7061
7062 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007063 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
7064
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007065 if (status != 0)
7066 return status;
7067
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007068 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007069 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08007070 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08007071 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
7072 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007073 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08007074
7075 in_update_effect_list(enable, effect, &in->aec_list);
7076 enable = !list_empty(&in->aec_list);
7077 if (enable == in->enable_aec)
7078 goto exit;
7079
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007080 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007081 ALOGD("AEC enable %d", enable);
7082
Aalique Grahame22e49102018-12-18 14:23:57 -08007083 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7084 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
7085 in->dev->enable_voicerx = enable;
7086 struct audio_usecase *usecase;
7087 struct listnode *node;
7088 list_for_each(node, &in->dev->usecase_list) {
7089 usecase = node_to_item(node, struct audio_usecase, list);
7090 if (usecase->type == PCM_PLAYBACK)
7091 select_devices(in->dev, usecase->id);
7092 }
7093 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007094 if (!in->standby) {
7095 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
7096 select_devices(in->dev, in->usecase);
7097 }
7098
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007099 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007100 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
7101
7102 in_update_effect_list(enable, effect, &in->ns_list);
7103 enable = !list_empty(&in->ns_list);
7104 if (enable == in->enable_ns)
7105 goto exit;
7106
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007107 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08007108 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007109 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08007110 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
7111 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07007112 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
7113 select_devices(in->dev, in->usecase);
7114 } else
7115 select_devices(in->dev, in->usecase);
7116 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08007117 }
Carter Hsu2e429db2019-05-14 18:50:52 +08007118exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007119 pthread_mutex_unlock(&in->dev->lock);
7120 pthread_mutex_unlock(&in->lock);
7121
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007122 return 0;
7123}
7124
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007125static int in_add_audio_effect(const struct audio_stream *stream,
7126 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007127{
Eric Laurent994a6932013-07-17 11:51:42 -07007128 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007129 return add_remove_audio_effect(stream, effect, true);
7130}
7131
7132static int in_remove_audio_effect(const struct audio_stream *stream,
7133 effect_handle_t effect)
7134{
Eric Laurent994a6932013-07-17 11:51:42 -07007135 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07007136 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007137}
7138
Derek Chenf939fb72018-11-13 13:34:41 -08007139streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
7140 audio_io_handle_t input)
7141{
7142 struct listnode *node;
7143
7144 list_for_each(node, &dev->active_inputs_list) {
7145 streams_input_ctxt_t *in_ctxt = node_to_item(node,
7146 streams_input_ctxt_t,
7147 list);
7148 if (in_ctxt->input->capture_handle == input) {
7149 return in_ctxt;
7150 }
7151 }
7152 return NULL;
7153}
7154
7155streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
7156 audio_io_handle_t output)
7157{
7158 struct listnode *node;
7159
7160 list_for_each(node, &dev->active_outputs_list) {
7161 streams_output_ctxt_t *out_ctxt = node_to_item(node,
7162 streams_output_ctxt_t,
7163 list);
7164 if (out_ctxt->output->handle == output) {
7165 return out_ctxt;
7166 }
7167 }
7168 return NULL;
7169}
7170
Haynes Mathew George16081042017-05-31 17:16:49 -07007171static int in_stop(const struct audio_stream_in* stream)
7172{
7173 struct stream_in *in = (struct stream_in *)stream;
7174 struct audio_device *adev = in->dev;
7175
7176 int ret = -ENOSYS;
7177 ALOGV("%s", __func__);
7178 pthread_mutex_lock(&adev->lock);
7179 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7180 in->capture_started && in->pcm != NULL) {
7181 pcm_stop(in->pcm);
7182 ret = stop_input_stream(in);
7183 in->capture_started = false;
7184 }
7185 pthread_mutex_unlock(&adev->lock);
7186 return ret;
7187}
7188
7189static int in_start(const struct audio_stream_in* stream)
7190{
7191 struct stream_in *in = (struct stream_in *)stream;
7192 struct audio_device *adev = in->dev;
7193 int ret = -ENOSYS;
7194
7195 ALOGV("%s in %p", __func__, in);
7196 pthread_mutex_lock(&adev->lock);
7197 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
7198 !in->capture_started && in->pcm != NULL) {
7199 if (!in->capture_started) {
7200 ret = start_input_stream(in);
7201 if (ret == 0) {
7202 in->capture_started = true;
7203 }
7204 }
7205 }
7206 pthread_mutex_unlock(&adev->lock);
7207 return ret;
7208}
7209
Phil Burke0a86d12019-02-16 22:28:11 -08007210// Read offset for the positional timestamp from a persistent vendor property.
7211// This is to workaround apparent inaccuracies in the timing information that
7212// is used by the AAudio timing model. The inaccuracies can cause glitches.
7213static int64_t in_get_mmap_time_offset() {
7214 const int32_t kDefaultOffsetMicros = 0;
7215 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08007216 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08007217 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
7218 return mmap_time_offset_micros * (int64_t)1000;
7219}
7220
Haynes Mathew George16081042017-05-31 17:16:49 -07007221static int in_create_mmap_buffer(const struct audio_stream_in *stream,
7222 int32_t min_size_frames,
7223 struct audio_mmap_buffer_info *info)
7224{
7225 struct stream_in *in = (struct stream_in *)stream;
7226 struct audio_device *adev = in->dev;
7227 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07007228 unsigned int offset1 = 0;
7229 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007230 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07007231 uint32_t mmap_size = 0;
7232 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07007233
7234 pthread_mutex_lock(&adev->lock);
7235 ALOGV("%s in %p", __func__, in);
7236
Sharad Sanglec6f32552018-05-04 16:15:38 +05307237 if (CARD_STATUS_OFFLINE == in->card_status||
7238 CARD_STATUS_OFFLINE == adev->card_status) {
7239 ALOGW("in->card_status or adev->card_status offline, try again");
7240 ret = -EIO;
7241 goto exit;
7242 }
7243
Haynes Mathew George16081042017-05-31 17:16:49 -07007244 if (info == NULL || min_size_frames == 0) {
7245 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
7246 ret = -EINVAL;
7247 goto exit;
7248 }
7249 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
7250 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
7251 ALOGV("%s in %p", __func__, in);
7252 ret = -ENOSYS;
7253 goto exit;
7254 }
7255 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
7256 if (in->pcm_device_id < 0) {
7257 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
7258 __func__, in->pcm_device_id, in->usecase);
7259 ret = -EINVAL;
7260 goto exit;
7261 }
7262
7263 adjust_mmap_period_count(&in->config, min_size_frames);
7264
7265 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7266 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7267 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7268 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307269 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307270 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7271 in->card_status = CARD_STATUS_OFFLINE;
7272 adev->card_status = CARD_STATUS_OFFLINE;
7273 ret = -EIO;
7274 goto exit;
7275 }
7276
Haynes Mathew George16081042017-05-31 17:16:49 -07007277 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7278 step = "open";
7279 ret = -ENODEV;
7280 goto exit;
7281 }
7282
7283 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7284 if (ret < 0) {
7285 step = "begin";
7286 goto exit;
7287 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007288
Arun Mirpuri5d170872019-03-26 13:21:31 -07007289 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7290 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7291 info->burst_size_frames = in->config.period_size;
7292 ret = platform_get_mmap_data_fd(adev->platform,
7293 in->pcm_device_id, 1 /*capture*/,
7294 &info->shared_memory_fd,
7295 &mmap_size);
7296 if (ret < 0) {
7297 // Fall back to non exclusive mode
7298 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7299 } else {
Phil Burkd898ba62019-06-20 12:49:01 -07007300 in->mmap_shared_memory_fd = info->shared_memory_fd; // for closing later
7301 ALOGV("%s: opened mmap_shared_memory_fd = %d", __func__, in->mmap_shared_memory_fd);
7302
Arun Mirpuri5d170872019-03-26 13:21:31 -07007303 if (mmap_size < buffer_size) {
7304 step = "mmap";
7305 goto exit;
7306 }
7307 // FIXME: indicate exclusive mode support by returning a negative buffer size
7308 info->buffer_size_frames *= -1;
7309 }
7310
7311 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007312
7313 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7314 if (ret < 0) {
7315 step = "commit";
7316 goto exit;
7317 }
7318
Phil Burke0a86d12019-02-16 22:28:11 -08007319 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7320
Haynes Mathew George16081042017-05-31 17:16:49 -07007321 in->standby = false;
7322 ret = 0;
7323
7324 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7325 __func__, info->shared_memory_address, info->buffer_size_frames);
7326
7327exit:
7328 if (ret != 0) {
7329 if (in->pcm == NULL) {
7330 ALOGE("%s: %s - %d", __func__, step, ret);
7331 } else {
7332 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7333 pcm_close(in->pcm);
7334 in->pcm = NULL;
7335 }
7336 }
7337 pthread_mutex_unlock(&adev->lock);
7338 return ret;
7339}
7340
7341static int in_get_mmap_position(const struct audio_stream_in *stream,
7342 struct audio_mmap_position *position)
7343{
7344 struct stream_in *in = (struct stream_in *)stream;
7345 ALOGVV("%s", __func__);
7346 if (position == NULL) {
7347 return -EINVAL;
7348 }
7349 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7350 return -ENOSYS;
7351 }
7352 if (in->pcm == NULL) {
7353 return -ENOSYS;
7354 }
7355 struct timespec ts = { 0, 0 };
7356 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7357 if (ret < 0) {
7358 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7359 return ret;
7360 }
Phil Burke0a86d12019-02-16 22:28:11 -08007361 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7362 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007363 return 0;
7364}
7365
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307366static int in_get_active_microphones(const struct audio_stream_in *stream,
7367 struct audio_microphone_characteristic_t *mic_array,
7368 size_t *mic_count) {
7369 struct stream_in *in = (struct stream_in *)stream;
7370 struct audio_device *adev = in->dev;
7371 ALOGVV("%s", __func__);
7372
7373 lock_input_stream(in);
7374 pthread_mutex_lock(&adev->lock);
7375 int ret = platform_get_active_microphones(adev->platform,
7376 audio_channel_count_from_in_mask(in->channel_mask),
7377 in->usecase, mic_array, mic_count);
7378 pthread_mutex_unlock(&adev->lock);
7379 pthread_mutex_unlock(&in->lock);
7380
7381 return ret;
7382}
7383
7384static int adev_get_microphones(const struct audio_hw_device *dev,
7385 struct audio_microphone_characteristic_t *mic_array,
7386 size_t *mic_count) {
7387 struct audio_device *adev = (struct audio_device *)dev;
7388 ALOGVV("%s", __func__);
7389
7390 pthread_mutex_lock(&adev->lock);
7391 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7392 pthread_mutex_unlock(&adev->lock);
7393
7394 return ret;
7395}
juyuchendb308c22019-01-21 11:57:17 -07007396
7397static void in_update_sink_metadata(struct audio_stream_in *stream,
7398 const struct sink_metadata *sink_metadata) {
7399
7400 if (stream == NULL
7401 || sink_metadata == NULL
7402 || sink_metadata->tracks == NULL) {
7403 return;
7404 }
7405
7406 int error = 0;
7407 struct stream_in *in = (struct stream_in *)stream;
7408 struct audio_device *adev = in->dev;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007409 struct listnode devices;
7410
7411 list_init(&devices);
juyuchendb308c22019-01-21 11:57:17 -07007412
7413 if (sink_metadata->track_count != 0)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007414 reassign_device_list(&devices, sink_metadata->tracks->dest_device, "");
juyuchendb308c22019-01-21 11:57:17 -07007415
7416 lock_input_stream(in);
7417 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007418 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, get_device_types(&devices));
juyuchendb308c22019-01-21 11:57:17 -07007419
7420 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007421 && !list_empty(&devices)
juyuchendb308c22019-01-21 11:57:17 -07007422 && adev->voice_tx_output != NULL) {
7423 /* Use the rx device from afe-proxy record to route voice call because
7424 there is no routing if tx device is on primary hal and rx device
7425 is on other hal during voice call. */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007426 assign_devices(&adev->voice_tx_output->device_list, &devices);
juyuchendb308c22019-01-21 11:57:17 -07007427
7428 if (!voice_is_call_state_active(adev)) {
7429 if (adev->mode == AUDIO_MODE_IN_CALL) {
7430 adev->current_call_output = adev->voice_tx_output;
7431 error = voice_start_call(adev);
7432 if (error != 0)
7433 ALOGE("%s: start voice call failed %d", __func__, error);
7434 }
7435 } else {
7436 adev->current_call_output = adev->voice_tx_output;
7437 voice_update_devices_for_all_voice_usecases(adev);
7438 }
7439 }
7440
7441 pthread_mutex_unlock(&adev->lock);
7442 pthread_mutex_unlock(&in->lock);
7443}
7444
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307445int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007446 audio_io_handle_t handle,
7447 audio_devices_t devices,
7448 audio_output_flags_t flags,
7449 struct audio_config *config,
7450 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007451 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007452{
7453 struct audio_device *adev = (struct audio_device *)dev;
7454 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307455 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007456 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007457 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307458 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007459 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7460 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7461 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7462 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007463 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007464 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7465 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007466 bool force_haptic_path =
7467 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007468 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007469
kunleizdff872d2018-08-20 14:40:33 +08007470 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007471 is_usb_dev = false;
7472 devices = AUDIO_DEVICE_OUT_SPEAKER;
7473 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7474 __func__, devices);
7475 }
7476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007477 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307478
Rahul Sharma99770982019-03-06 17:05:26 +05307479 pthread_mutex_lock(&adev->lock);
7480 if (out_get_stream(adev, handle) != NULL) {
7481 ALOGW("%s, output stream already opened", __func__);
7482 ret = -EEXIST;
7483 }
7484 pthread_mutex_unlock(&adev->lock);
7485 if (ret)
7486 return ret;
7487
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007488 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7489
Mingming Yin3a941d42016-02-17 18:08:05 -08007490 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007491 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7492 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307493
7494
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007495 if (!out) {
7496 return -ENOMEM;
7497 }
7498
Haynes Mathew George204045b2015-02-25 20:32:03 -08007499 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007500 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307501 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007502 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007503 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7504
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007505 if (devices == AUDIO_DEVICE_NONE)
7506 devices = AUDIO_DEVICE_OUT_SPEAKER;
7507
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007508 out->flags = flags;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007509 list_init(&out->device_list);
7510 update_device_list(&out->device_list, devices, address, true /* add devices */);
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007511 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007512 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007513 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307514 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307515 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7516 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7517 else
7518 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007519 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007520 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007521 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307522 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307523 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307524 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007525 out->hal_output_suspend_supported = 0;
7526 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307527 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307528 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307529 out->pspd_coeff_sent = false;
Phil Burkd898ba62019-06-20 12:49:01 -07007530 out->mmap_shared_memory_fd = -1; // not open
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007531
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307532 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307533 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007534 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7535
Aalique Grahame22e49102018-12-18 14:23:57 -08007536 if (direct_dev &&
7537 (audio_is_linear_pcm(out->format) ||
7538 config->format == AUDIO_FORMAT_DEFAULT) &&
7539 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7540 audio_format_t req_format = config->format;
7541 audio_channel_mask_t req_channel_mask = config->channel_mask;
7542 uint32_t req_sample_rate = config->sample_rate;
7543
7544 pthread_mutex_lock(&adev->lock);
7545 if (is_hdmi) {
7546 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7547 ret = read_hdmi_sink_caps(out);
7548 if (config->sample_rate == 0)
7549 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7550 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7551 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7552 if (config->format == AUDIO_FORMAT_DEFAULT)
7553 config->format = AUDIO_FORMAT_PCM_16_BIT;
7554 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007555 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7556 &config->format,
7557 &out->supported_formats[0],
7558 MAX_SUPPORTED_FORMATS,
7559 &config->channel_mask,
7560 &out->supported_channel_masks[0],
7561 MAX_SUPPORTED_CHANNEL_MASKS,
7562 &config->sample_rate,
7563 &out->supported_sample_rates[0],
7564 MAX_SUPPORTED_SAMPLE_RATES);
7565 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007566 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007567
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007568 pthread_mutex_unlock(&adev->lock);
7569 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007570 if (ret == -ENOSYS) {
7571 /* ignore and go with default */
7572 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007573 }
7574 // For MMAP NO IRQ, allow conversions in ADSP
7575 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7576 goto error_open;
7577 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007578 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007579 goto error_open;
7580 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007581
7582 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7583 config->sample_rate = req_sample_rate;
7584 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7585 config->channel_mask = req_channel_mask;
7586 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7587 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007588 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007589
7590 out->sample_rate = config->sample_rate;
7591 out->channel_mask = config->channel_mask;
7592 out->format = config->format;
7593 if (is_hdmi) {
7594 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7595 out->config = pcm_config_hdmi_multi;
7596 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7597 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7598 out->config = pcm_config_mmap_playback;
7599 out->stream.start = out_start;
7600 out->stream.stop = out_stop;
7601 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7602 out->stream.get_mmap_position = out_get_mmap_position;
7603 } else {
7604 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7605 out->config = pcm_config_hifi;
7606 }
7607
7608 out->config.rate = out->sample_rate;
7609 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7610 if (is_hdmi) {
7611 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7612 audio_bytes_per_sample(out->format));
7613 }
7614 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007615 }
7616
Derek Chenf6318be2017-06-12 17:16:24 -04007617 /* validate bus device address */
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007618 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04007619 /* extract car audio stream index */
7620 out->car_audio_stream =
7621 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7622 if (out->car_audio_stream < 0) {
7623 ALOGE("%s: invalid car audio stream %x",
7624 __func__, out->car_audio_stream);
7625 ret = -EINVAL;
7626 goto error_open;
7627 }
Derek Chen5f67a942020-02-24 23:08:13 -08007628 ALOGV("%s: car_audio_stream %x", __func__, out->car_audio_stream);
Derek Chenf6318be2017-06-12 17:16:24 -04007629 }
7630
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007631 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007632 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007633 if (!voice_extn_is_compress_voip_supported()) {
7634 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7635 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007636 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7637 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007638 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7639 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007640 out->volume_l = INVALID_OUT_VOLUME;
7641 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007642
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007643 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007644 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007645 uint32_t channel_count =
7646 audio_channel_count_from_out_mask(out->channel_mask);
7647 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7648 out->sample_rate, out->format,
7649 channel_count, false);
7650 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7651 if (frame_size != 0)
7652 out->config.period_size = buffer_size / frame_size;
7653 else
7654 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007655 }
7656 } else {
7657 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7658 voice_extn_compress_voip_is_active(out->dev)) &&
7659 (voice_extn_compress_voip_is_config_supported(config))) {
7660 ret = voice_extn_compress_voip_open_output_stream(out);
7661 if (ret != 0) {
7662 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7663 __func__, ret);
7664 goto error_open;
7665 }
Sujin Panicker19027262019-09-16 18:28:06 +05307666 } else {
7667 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7668 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007669 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007670 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007671 } else if (audio_is_linear_pcm(out->format) &&
7672 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7673 out->channel_mask = config->channel_mask;
7674 out->sample_rate = config->sample_rate;
7675 out->format = config->format;
7676 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7677 // does this change?
7678 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7679 out->config.rate = config->sample_rate;
7680 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7681 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7682 audio_bytes_per_sample(config->format));
7683 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007684 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307685 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307686 pthread_mutex_lock(&adev->lock);
7687 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7688 pthread_mutex_unlock(&adev->lock);
7689
7690 // reject offload during card offline to allow
7691 // fallback to s/w paths
7692 if (offline) {
7693 ret = -ENODEV;
7694 goto error_open;
7695 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007696
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007697 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7698 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7699 ALOGE("%s: Unsupported Offload information", __func__);
7700 ret = -EINVAL;
7701 goto error_open;
7702 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007703
Atul Khare3fa6e542017-08-09 00:56:17 +05307704 if (config->offload_info.format == 0)
7705 config->offload_info.format = config->format;
7706 if (config->offload_info.sample_rate == 0)
7707 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007708
Mingming Yin90310102013-11-13 16:57:00 -08007709 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307710 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007711 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007712 ret = -EINVAL;
7713 goto error_open;
7714 }
7715
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007716 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7717 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7718 (audio_extn_passthru_is_passthrough_stream(out)) &&
7719 !((config->sample_rate == 48000) ||
7720 (config->sample_rate == 96000) ||
7721 (config->sample_rate == 192000))) {
7722 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7723 __func__, config->sample_rate, config->offload_info.format);
7724 ret = -EINVAL;
7725 goto error_open;
7726 }
7727
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007728 out->compr_config.codec = (struct snd_codec *)
7729 calloc(1, sizeof(struct snd_codec));
7730
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007731 if (!out->compr_config.codec) {
7732 ret = -ENOMEM;
7733 goto error_open;
7734 }
7735
Dhananjay Kumarac341582017-02-23 23:42:25 +05307736 out->stream.pause = out_pause;
7737 out->stream.resume = out_resume;
7738 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307739 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307740 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007741 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307742 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007743 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307744 } else {
7745 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7746 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007747 }
vivek mehta446c3962015-09-14 10:57:35 -07007748
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307749 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7750 ALOGD("%s: Setting latency mode to true", __func__);
Meng Wang4c32fb42020-01-16 17:57:11 +08007751#ifdef AUDIO_GKI_ENABLED
7752 /* out->compr_config.codec->reserved[1] is for flags */
7753 out->compr_config.codec->reserved[1] |= audio_extn_utils_get_perf_mode_flag();
7754#else
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307755 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
Meng Wang4c32fb42020-01-16 17:57:11 +08007756#endif
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307757 }
7758
vivek mehta446c3962015-09-14 10:57:35 -07007759 if (out->usecase == USECASE_INVALID) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08007760 if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
Mingming Yin3a941d42016-02-17 18:08:05 -08007761 config->format == 0 && config->sample_rate == 0 &&
7762 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007763 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007764 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7765 } else {
7766 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7767 ret = -EEXIST;
7768 goto error_open;
7769 }
vivek mehta446c3962015-09-14 10:57:35 -07007770 }
7771
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007772 if (config->offload_info.channel_mask)
7773 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007774 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007775 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007776 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007777 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307778 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007779 ret = -EINVAL;
7780 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007781 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007782
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007783 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007784 out->sample_rate = config->offload_info.sample_rate;
7785
Mingming Yin3ee55c62014-08-04 14:23:35 -07007786 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007787
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307788 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307789 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307790 audio_extn_dolby_send_ddp_endp_params(adev);
7791 audio_extn_dolby_set_dmid(adev);
7792 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007793
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007794 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007795 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007796 out->compr_config.codec->bit_rate =
7797 config->offload_info.bit_rate;
7798 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307799 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007800 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307801 /* Update bit width only for non passthrough usecases.
7802 * For passthrough usecases, the output will always be opened @16 bit
7803 */
7804 if (!audio_extn_passthru_is_passthrough_stream(out))
7805 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307806
7807 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
Meng Wang4c32fb42020-01-16 17:57:11 +08007808#ifdef AUDIO_GKI_ENABLED
7809 /* out->compr_config.codec->reserved[1] is for flags */
7810 out->compr_config.codec->reserved[1] |= COMPRESSED_TIMESTAMP_FLAG;
7811 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->reserved[1]);
7812#else
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307813 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7814 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
Meng Wang4c32fb42020-01-16 17:57:11 +08007815#endif
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307816
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007817 /*TODO: Do we need to change it for passthrough */
7818 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007819
Manish Dewangana6fc5442015-08-24 20:30:31 +05307820 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7821 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307822 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307823 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307824 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7825 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307826
7827 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7828 AUDIO_FORMAT_PCM) {
7829
7830 /*Based on platform support, configure appropriate alsa format for corresponding
7831 *hal input format.
7832 */
7833 out->compr_config.codec->format = hal_format_to_alsa(
7834 config->offload_info.format);
7835
Ashish Jain83a6cc22016-06-28 14:34:17 +05307836 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307837 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307838 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307839
Dhananjay Kumarac341582017-02-23 23:42:25 +05307840 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307841 *hal input format and alsa format might differ based on platform support.
7842 */
7843 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307844 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307845
7846 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7847
Deeraj Soman93155a62019-09-30 19:00:37 +05307848 if (property_get_bool("vendor.audio.offload.buffer.duration.enabled", false)) {
7849 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7850 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7851 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7852 }
Deeraj Soman65358ab2019-02-07 15:40:49 +05307853
Ashish Jainf1eaa582016-05-23 20:54:24 +05307854 /* Check if alsa session is configured with the same format as HAL input format,
7855 * if not then derive correct fragment size needed to accomodate the
7856 * conversion of HAL input format to alsa format.
7857 */
7858 audio_extn_utils_update_direct_pcm_fragment_size(out);
7859
7860 /*if hal input and output fragment size is different this indicates HAL input format is
7861 *not same as the alsa format
7862 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307863 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307864 /*Allocate a buffer to convert input data to the alsa configured format.
7865 *size of convert buffer is equal to the size required to hold one fragment size
7866 *worth of pcm data, this is because flinger does not write more than fragment_size
7867 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307868 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7869 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307870 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7871 ret = -ENOMEM;
7872 goto error_open;
7873 }
7874 }
7875 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7876 out->compr_config.fragment_size =
7877 audio_extn_passthru_get_buffer_size(&config->offload_info);
7878 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7879 } else {
7880 out->compr_config.fragment_size =
7881 platform_get_compress_offload_buffer_size(&config->offload_info);
7882 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7883 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007884
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307885 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7886 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7887 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007888 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307889 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007890
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307891 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7892 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7893 }
7894
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007895 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7896 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007897
Manish Dewangan69426c82017-01-30 17:35:36 +05307898 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7899 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7900 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7901 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7902 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7903 } else {
7904 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7905 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007906
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307907 memset(&out->channel_map_param, 0,
7908 sizeof(struct audio_out_channel_map_param));
7909
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007910 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307911 out->send_next_track_params = false;
7912 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007913 out->offload_state = OFFLOAD_STATE_IDLE;
7914 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007915 out->writeAt.tv_sec = 0;
7916 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007917
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007918 audio_extn_dts_create_state_notifier_node(out->usecase);
7919
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007920 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7921 __func__, config->offload_info.version,
7922 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307923
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307924 /* Check if DSD audio format is supported in codec
7925 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307926 */
7927
7928 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307929 (!platform_check_codec_dsd_support(adev->platform) ||
7930 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307931 ret = -EINVAL;
7932 goto error_open;
7933 }
7934
Ashish Jain5106d362016-05-11 19:23:33 +05307935 /* Disable gapless if any of the following is true
7936 * passthrough playback
7937 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307938 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307939 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307940 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307941 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007942 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307943 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307944 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307945 check_and_set_gapless_mode(adev, false);
7946 } else
7947 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007948
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307949 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007950 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7951 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307952 if (config->format == AUDIO_FORMAT_DSD) {
7953 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
Meng Wang4c32fb42020-01-16 17:57:11 +08007954#ifdef AUDIO_GKI_ENABLED
7955 /* out->compr_config.codec->reserved[0] is for compr_passthr */
7956 out->compr_config.codec->reserved[0] = PASSTHROUGH_DSD;
7957#else
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307958 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
Meng Wang4c32fb42020-01-16 17:57:11 +08007959#endif
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307960 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007961
7962 create_offload_callback_thread(out);
7963
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007964 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007965 switch (config->sample_rate) {
7966 case 0:
7967 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7968 break;
7969 case 8000:
7970 case 16000:
7971 case 48000:
7972 out->sample_rate = config->sample_rate;
7973 break;
7974 default:
7975 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7976 config->sample_rate);
7977 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7978 ret = -EINVAL;
7979 goto error_open;
7980 }
7981 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7982 switch (config->channel_mask) {
7983 case AUDIO_CHANNEL_NONE:
7984 case AUDIO_CHANNEL_OUT_STEREO:
7985 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7986 break;
7987 default:
7988 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7989 config->channel_mask);
7990 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7991 ret = -EINVAL;
7992 goto error_open;
7993 }
7994 switch (config->format) {
7995 case AUDIO_FORMAT_DEFAULT:
7996 case AUDIO_FORMAT_PCM_16_BIT:
7997 out->format = AUDIO_FORMAT_PCM_16_BIT;
7998 break;
7999 default:
8000 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
8001 config->format);
8002 config->format = AUDIO_FORMAT_PCM_16_BIT;
8003 ret = -EINVAL;
8004 goto error_open;
8005 }
8006
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05308007 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008008 if (ret != 0) {
8009 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07008010 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07008011 goto error_open;
8012 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008013 } else if (is_single_device_type_equal(&out->device_list,
8014 AUDIO_DEVICE_OUT_TELEPHONY_TX)) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008015 switch (config->sample_rate) {
8016 case 0:
8017 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
8018 break;
8019 case 8000:
8020 case 16000:
8021 case 48000:
8022 out->sample_rate = config->sample_rate;
8023 break;
8024 default:
8025 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
8026 config->sample_rate);
8027 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8028 ret = -EINVAL;
8029 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008030 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008031 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
8032 switch (config->channel_mask) {
8033 case AUDIO_CHANNEL_NONE:
8034 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8035 break;
8036 case AUDIO_CHANNEL_OUT_STEREO:
8037 out->channel_mask = config->channel_mask;
8038 break;
8039 default:
8040 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
8041 config->channel_mask);
8042 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8043 ret = -EINVAL;
8044 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008045 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008046 switch (config->format) {
8047 case AUDIO_FORMAT_DEFAULT:
8048 out->format = AUDIO_FORMAT_PCM_16_BIT;
8049 break;
8050 case AUDIO_FORMAT_PCM_16_BIT:
8051 out->format = config->format;
8052 break;
8053 default:
8054 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
8055 config->format);
8056 config->format = AUDIO_FORMAT_PCM_16_BIT;
8057 ret = -EINVAL;
8058 break;
8059 }
8060 if (ret != 0)
8061 goto error_open;
8062
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008063 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
8064 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08008065 out->config.rate = out->sample_rate;
8066 out->config.channels =
8067 audio_channel_count_from_out_mask(out->channel_mask);
8068 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008069 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008070 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05308071 unsigned int channels = 0;
8072 /*Update config params to default if not set by the caller*/
8073 if (config->sample_rate == 0)
8074 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
8075 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8076 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
8077 if (config->format == AUDIO_FORMAT_DEFAULT)
8078 config->format = AUDIO_FORMAT_PCM_16_BIT;
8079
8080 channels = audio_channel_count_from_out_mask(out->channel_mask);
8081
Varun Balaraje49253e2017-07-06 19:48:56 +05308082 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
8083 out->usecase = get_interactive_usecase(adev);
8084 out->config = pcm_config_low_latency;
8085 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05308086 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07008087 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
8088 out->flags);
8089 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07008090 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
8091 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
8092 out->config = pcm_config_mmap_playback;
8093 out->stream.start = out_start;
8094 out->stream.stop = out_stop;
8095 out->stream.create_mmap_buffer = out_create_mmap_buffer;
8096 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308097 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
8098 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08008099 out->hal_output_suspend_supported =
8100 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
8101 out->dynamic_pm_qos_config_supported =
8102 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
8103 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08008104 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
8105 } else {
8106 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
8107 //the mixer path will be a string similar to "low-latency-playback resume"
8108 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
8109 strlcat(out->pm_qos_mixer_path,
8110 " resume", MAX_MIXER_PATH_LEN);
8111 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
8112 out->pm_qos_mixer_path);
8113 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308114 out->config = pcm_config_low_latency;
8115 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
8116 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
8117 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05308118 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
8119 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
8120 if (out->config.period_size <= 0) {
8121 ALOGE("Invalid configuration period size is not valid");
8122 ret = -EINVAL;
8123 goto error_open;
8124 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008125 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
8126 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
8127 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08008128 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
8129 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
8130 out->config = pcm_config_haptics_audio;
8131 if (force_haptic_path)
8132 adev->haptics_config = pcm_config_haptics_audio;
8133 else
8134 adev->haptics_config = pcm_config_haptics;
8135
8136 out->config.channels =
8137 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
8138
8139 if (force_haptic_path) {
8140 out->config.channels = 1;
8141 adev->haptics_config.channels = 1;
8142 } else
8143 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 -08008144 } else if (compare_device_type(&out->device_list, AUDIO_DEVICE_OUT_BUS)) {
Derek Chenf6318be2017-06-12 17:16:24 -04008145 ret = audio_extn_auto_hal_open_output_stream(out);
8146 if (ret) {
8147 ALOGE("%s: Failed to open output stream for bus device", __func__);
8148 ret = -EINVAL;
8149 goto error_open;
8150 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05308151 } else {
8152 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008153 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
8154 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308155 }
8156 out->hal_ip_format = format = out->format;
8157 out->config.format = hal_format_to_pcm(out->hal_ip_format);
8158 out->hal_op_format = pcm_format_to_hal(out->config.format);
8159 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
8160 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07008161 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05308162 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05308163 if (out->hal_ip_format != out->hal_op_format) {
8164 uint32_t buffer_size = out->config.period_size *
8165 format_to_bitwidth_table[out->hal_op_format] *
8166 out->config.channels;
8167 out->convert_buffer = calloc(1, buffer_size);
8168 if (out->convert_buffer == NULL){
8169 ALOGE("Allocation failed for convert buffer for size %d",
8170 out->compr_config.fragment_size);
8171 ret = -ENOMEM;
8172 goto error_open;
8173 }
8174 ALOGD("Convert buffer allocated of size %d", buffer_size);
8175 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008176 }
8177
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008178 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
8179 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05308180
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07008181 /* TODO remove this hardcoding and check why width is zero*/
8182 if (out->bit_width == 0)
8183 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308184 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07008185 &adev->streams_output_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008186 &out->device_list, out->flags,
8187 out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05308188 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05308189 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08008190 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08008191 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
8192 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008193 if(adev->primary_output == NULL)
8194 adev->primary_output = out;
8195 else {
8196 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008197 ret = -EEXIST;
8198 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008199 }
8200 }
8201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008202 /* Check if this usecase is already existing */
8203 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07008204 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
8205 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008206 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008207 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008208 ret = -EEXIST;
8209 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008210 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008212 pthread_mutex_unlock(&adev->lock);
8213
8214 out->stream.common.get_sample_rate = out_get_sample_rate;
8215 out->stream.common.set_sample_rate = out_set_sample_rate;
8216 out->stream.common.get_buffer_size = out_get_buffer_size;
8217 out->stream.common.get_channels = out_get_channels;
8218 out->stream.common.get_format = out_get_format;
8219 out->stream.common.set_format = out_set_format;
8220 out->stream.common.standby = out_standby;
8221 out->stream.common.dump = out_dump;
8222 out->stream.common.set_parameters = out_set_parameters;
8223 out->stream.common.get_parameters = out_get_parameters;
8224 out->stream.common.add_audio_effect = out_add_audio_effect;
8225 out->stream.common.remove_audio_effect = out_remove_audio_effect;
8226 out->stream.get_latency = out_get_latency;
8227 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08008228#ifdef NO_AUDIO_OUT
8229 out->stream.write = out_write_for_no_output;
8230#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008231 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08008232#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008233 out->stream.get_render_position = out_get_render_position;
8234 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008235 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008236
Haynes Mathew George16081042017-05-31 17:16:49 -07008237 if (out->realtime)
8238 out->af_period_multiplier = af_period_multiplier;
8239 else
8240 out->af_period_multiplier = 1;
8241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008242 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07008243 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07008244 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008245
8246 config->format = out->stream.common.get_format(&out->stream.common);
8247 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
8248 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308249 register_format(out->format, out->supported_formats);
8250 register_channel_mask(out->channel_mask, out->supported_channel_masks);
8251 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008252
Aalique Grahame22e49102018-12-18 14:23:57 -08008253 out->error_log = error_log_create(
8254 ERROR_LOG_ENTRIES,
8255 1000000000 /* aggregate consecutive identical errors within one second in ns */);
8256
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308257 /*
8258 By locking output stream before registering, we allow the callback
8259 to update stream's state only after stream's initial state is set to
8260 adev state.
8261 */
8262 lock_output_stream(out);
8263 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
8264 pthread_mutex_lock(&adev->lock);
8265 out->card_status = adev->card_status;
8266 pthread_mutex_unlock(&adev->lock);
8267 pthread_mutex_unlock(&out->lock);
8268
Aalique Grahame22e49102018-12-18 14:23:57 -08008269 stream_app_type_cfg_init(&out->app_type_cfg);
8270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008271 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308272 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07008273 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008274
8275 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
8276 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
8277 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008278 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05308279 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008280 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07008281 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05308282 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8283 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008284 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8285 out->usecase, PCM_PLAYBACK);
8286 hdlr_stream_cfg.flags = out->flags;
8287 hdlr_stream_cfg.type = PCM_PLAYBACK;
8288 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8289 &hdlr_stream_cfg);
8290 if (ret) {
8291 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8292 out->adsp_hdlr_stream_handle = NULL;
8293 }
8294 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308295 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8296 is_direct_passthough, false);
8297 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8298 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008299 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008300 if (ret < 0) {
8301 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8302 out->ip_hdlr_handle = NULL;
8303 }
8304 }
Derek Chenf939fb72018-11-13 13:34:41 -08008305
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008306 ret = io_streams_map_insert(adev, &out->stream.common,
8307 out->handle, AUDIO_PATCH_HANDLE_NONE);
8308 if (ret != 0)
8309 goto error_open;
8310
Derek Chenf939fb72018-11-13 13:34:41 -08008311 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8312 calloc(1, sizeof(streams_output_ctxt_t));
8313 if (out_ctxt == NULL) {
8314 ALOGE("%s fail to allocate output ctxt", __func__);
8315 ret = -ENOMEM;
8316 goto error_open;
8317 }
8318 out_ctxt->output = out;
8319
8320 pthread_mutex_lock(&adev->lock);
8321 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8322 pthread_mutex_unlock(&adev->lock);
8323
Eric Laurent994a6932013-07-17 11:51:42 -07008324 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008325 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008326
8327error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308328 if (out->convert_buffer)
8329 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008330 free(out);
8331 *stream_out = NULL;
8332 ALOGD("%s: exit: ret %d", __func__, ret);
8333 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008334}
8335
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308336void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008337 struct audio_stream_out *stream)
8338{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008339 struct stream_out *out = (struct stream_out *)stream;
8340 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008341 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008342
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008343 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308344
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07008345 io_streams_map_remove(adev, out->handle);
8346
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308347 // must deregister from sndmonitor first to prevent races
8348 // between the callback and close_stream
8349 audio_extn_snd_mon_unregister_listener(out);
8350
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008351 /* close adsp hdrl session before standby */
8352 if (out->adsp_hdlr_stream_handle) {
8353 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8354 if (ret)
8355 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8356 out->adsp_hdlr_stream_handle = NULL;
8357 }
8358
Manish Dewangan21a850a2017-08-14 12:03:55 +05308359 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008360 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8361 out->ip_hdlr_handle = NULL;
8362 }
8363
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008364 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308365 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008366 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308367 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308368 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008369 if(ret != 0)
8370 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8371 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008372 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008373 out_standby(&stream->common);
8374
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008375 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008376 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008377 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008378 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008379 if (out->compr_config.codec != NULL)
8380 free(out->compr_config.codec);
8381 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008382
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308383 out->a2dp_compress_mute = false;
8384
Varun Balaraje49253e2017-07-06 19:48:56 +05308385 if (is_interactive_usecase(out->usecase))
8386 free_interactive_usecase(adev, out->usecase);
8387
Ashish Jain83a6cc22016-06-28 14:34:17 +05308388 if (out->convert_buffer != NULL) {
8389 free(out->convert_buffer);
8390 out->convert_buffer = NULL;
8391 }
8392
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008393 if (adev->voice_tx_output == out)
8394 adev->voice_tx_output = NULL;
8395
Aalique Grahame22e49102018-12-18 14:23:57 -08008396 error_log_destroy(out->error_log);
8397 out->error_log = NULL;
8398
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308399 if (adev->primary_output == out)
8400 adev->primary_output = NULL;
8401
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008402 pthread_cond_destroy(&out->cond);
8403 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008404
8405 pthread_mutex_lock(&adev->lock);
8406 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8407 if (out_ctxt != NULL) {
8408 list_remove(&out_ctxt->list);
8409 free(out_ctxt);
8410 } else {
8411 ALOGW("%s, output stream already closed", __func__);
8412 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008413 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008414 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008415 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008416}
8417
8418static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8419{
8420 struct audio_device *adev = (struct audio_device *)dev;
8421 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008422 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008423 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008424 int ret;
8425 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008426 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008427 struct listnode *node;
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008428 int controller = -1, stream = -1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008429
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008430 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008431 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008432
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308433 if (!parms)
8434 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308435
Derek Chen6f293672019-04-01 01:40:24 -07008436 /* notify adev and input/output streams on the snd card status */
8437 adev_snd_mon_cb((void *)adev, parms);
8438
8439 list_for_each(node, &adev->active_outputs_list) {
8440 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8441 streams_output_ctxt_t,
8442 list);
8443 out_snd_mon_cb((void *)out_ctxt->output, parms);
8444 }
8445
8446 list_for_each(node, &adev->active_inputs_list) {
8447 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8448 streams_input_ctxt_t,
8449 list);
8450 in_snd_mon_cb((void *)in_ctxt->input, parms);
8451 }
8452
Zhou Songd6d71752019-05-21 18:08:51 +08008453 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308454 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8455 if (ret >= 0) {
8456 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008457 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308458 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008459 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308460 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008461 audio_extn_sco_reset_configuration();
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008462 }
8463 }
8464
8465 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8466 if (ret>=0) {
8467 if (!strncmp(value, "false", 5) &&
8468 audio_extn_a2dp_source_is_suspended()) {
8469 struct audio_usecase *usecase;
8470 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008471 list_for_each(node, &adev->usecase_list) {
8472 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008473 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008474 is_sco_in_device_type(&usecase->stream.in->device_list)) {
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008475 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008476 reassign_device_list(&usecase->stream.in->device_list,
8477 AUDIO_DEVICE_IN_BUILTIN_MIC, "");
Kunlei Zhangd96af8f2019-08-27 16:33:29 +08008478 select_devices(adev, usecase->id);
8479 }
Zhou Songd6d71752019-05-21 18:08:51 +08008480 }
8481 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308482 }
8483
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008484 status = voice_set_parameters(adev, parms);
8485 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008486 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008487
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008488 status = platform_set_parameters(adev->platform, parms);
8489 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008490 goto done;
8491
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008492 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8493 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008494 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008495 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8496 adev->bluetooth_nrec = true;
8497 else
8498 adev->bluetooth_nrec = false;
8499 }
8500
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008501 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8502 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008503 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8504 adev->screen_off = false;
8505 else
8506 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008507 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008508 }
8509
Eric Laurent4b084132018-10-19 17:33:43 -07008510 ret = str_parms_get_int(parms, "rotation", &val);
8511 if (ret >= 0) {
8512 bool reverse_speakers = false;
8513 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8514 switch (val) {
8515 // FIXME: note that the code below assumes that the speakers are in the correct placement
8516 // relative to the user when the device is rotated 90deg from its default rotation. This
8517 // assumption is device-specific, not platform-specific like this code.
8518 case 270:
8519 reverse_speakers = true;
8520 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8521 break;
8522 case 0:
8523 case 180:
8524 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8525 break;
8526 case 90:
8527 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8528 break;
8529 default:
8530 ALOGE("%s: unexpected rotation of %d", __func__, val);
8531 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008532 }
Eric Laurent4b084132018-10-19 17:33:43 -07008533 if (status == 0) {
8534 // check and set swap
8535 // - check if orientation changed and speaker active
8536 // - set rotation and cache the rotation value
8537 adev->camera_orientation =
8538 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8539 if (!audio_extn_is_maxx_audio_enabled())
8540 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8541 }
8542 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008543
Mingming Yin514a8bc2014-07-29 15:22:21 -07008544 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8545 if (ret >= 0) {
8546 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8547 adev->bt_wb_speech_enabled = true;
8548 else
8549 adev->bt_wb_speech_enabled = false;
8550 }
8551
Zhou Song12c29502019-03-16 10:37:18 +08008552 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8553 if (ret >= 0) {
8554 val = atoi(value);
8555 adev->swb_speech_mode = val;
8556 }
8557
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008558 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8559 if (ret >= 0) {
8560 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308561 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008562 if (audio_is_output_device(val) &&
8563 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008564 ALOGV("cache new ext disp type and edid");
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008565 platform_get_controller_stream_from_params(parms, &controller, &stream);
8566 platform_set_ext_display_device_v2(adev->platform, controller, stream);
8567 ret = platform_get_ext_disp_type_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008568 if (ret < 0) {
8569 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308570 } else {
Vignesh Kulothungan39fc6a22019-08-01 00:55:59 -07008571 platform_cache_edid_v2(adev->platform, controller, stream);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008572 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308573 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008574 /*
8575 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8576 * Per AudioPolicyManager, USB device is higher priority than WFD.
8577 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8578 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8579 * starting voice call on USB
8580 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008581 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308582 if (ret >= 0)
8583 audio_extn_usb_add_device(device, atoi(value));
8584
Zhou Song6f862822017-11-06 17:27:57 +08008585 if (!audio_extn_usb_is_tunnel_supported()) {
8586 ALOGV("detected USB connect .. disable proxy");
8587 adev->allow_afe_proxy_usage = false;
8588 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008589 }
8590 }
8591
8592 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8593 if (ret >= 0) {
8594 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308595 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008596 /*
8597 * The HDMI / Displayport disconnect handling has been moved to
8598 * audio extension to ensure that its parameters are not
8599 * invalidated prior to updating sysfs of the disconnect event
8600 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8601 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308602 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008603 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308604 if (ret >= 0)
8605 audio_extn_usb_remove_device(device, atoi(value));
8606
Zhou Song6f862822017-11-06 17:27:57 +08008607 if (!audio_extn_usb_is_tunnel_supported()) {
8608 ALOGV("detected USB disconnect .. enable proxy");
8609 adev->allow_afe_proxy_usage = true;
8610 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008611 }
8612 }
8613
Aalique Grahame22e49102018-12-18 14:23:57 -08008614 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008615 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008616
8617 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008618 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308619 struct audio_usecase *usecase;
8620 struct listnode *node;
8621 list_for_each(node, &adev->usecase_list) {
8622 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308623 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008624 is_a2dp_out_device_type(&usecase->device_list)) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308625 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008626 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308627 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008628 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308629 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308630 ALOGD("Switching to speaker and muting the stream before select_devices");
8631 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308632 //force device switch to re configure encoder
8633 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308634 ALOGD("Unmuting the stream after select_devices");
8635 usecase->stream.out->a2dp_compress_mute = false;
8636 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 +05308637 audio_extn_a2dp_set_handoff_mode(false);
8638 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308639 break;
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308640 } else if ((usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8641 usecase->stream.out->a2dp_compress_mute) {
8642 pthread_mutex_unlock(&adev->lock);
8643 lock_output_stream(usecase->stream.out);
8644 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008645 reassign_device_list(&usecase->stream.out->device_list,
8646 AUDIO_DEVICE_OUT_BLUETOOTH_A2DP, "");
Manisha Agarwal6a6fb9a2019-12-04 11:38:41 +05308647 check_a2dp_restore_l(adev, usecase->stream.out, true);
8648 pthread_mutex_unlock(&usecase->stream.out->lock);
8649 break;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308650 }
8651 }
8652 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008653
8654 //handle vr audio setparam
8655 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8656 value, sizeof(value));
8657 if (ret >= 0) {
8658 ALOGI("Setting vr mode to be %s", value);
8659 if (!strncmp(value, "true", 4)) {
8660 adev->vr_audio_mode_enabled = true;
8661 ALOGI("Setting vr mode to true");
8662 } else if (!strncmp(value, "false", 5)) {
8663 adev->vr_audio_mode_enabled = false;
8664 ALOGI("Setting vr mode to false");
8665 } else {
8666 ALOGI("wrong vr mode set");
8667 }
8668 }
8669
Eric Laurent4b084132018-10-19 17:33:43 -07008670 //FIXME: to be replaced by proper video capture properties API
8671 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8672 if (ret >= 0) {
8673 int camera_facing = CAMERA_FACING_BACK;
8674 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8675 camera_facing = CAMERA_FACING_FRONT;
8676 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8677 camera_facing = CAMERA_FACING_BACK;
8678 else {
8679 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8680 goto done;
8681 }
8682 adev->camera_orientation =
8683 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8684 struct audio_usecase *usecase;
8685 struct listnode *node;
8686 list_for_each(node, &adev->usecase_list) {
8687 usecase = node_to_item(node, struct audio_usecase, list);
8688 struct stream_in *in = usecase->stream.in;
8689 if (usecase->type == PCM_CAPTURE && in != NULL &&
8690 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8691 select_devices(adev, in->usecase);
8692 }
8693 }
8694 }
8695
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308696 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008697done:
8698 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008699 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308700error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008701 ALOGV("%s: exit with code(%d)", __func__, status);
8702 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008703}
8704
8705static char* adev_get_parameters(const struct audio_hw_device *dev,
8706 const char *keys)
8707{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308708 ALOGD("%s:%s", __func__, keys);
8709
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008710 struct audio_device *adev = (struct audio_device *)dev;
8711 struct str_parms *reply = str_parms_create();
8712 struct str_parms *query = str_parms_create_str(keys);
8713 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308714 char value[256] = {0};
8715 int ret = 0;
8716
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008717 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008718 if (reply) {
8719 str_parms_destroy(reply);
8720 }
8721 if (query) {
8722 str_parms_destroy(query);
8723 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008724 ALOGE("adev_get_parameters: failed to create query or reply");
8725 return NULL;
8726 }
8727
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008728 //handle vr audio getparam
8729
8730 ret = str_parms_get_str(query,
8731 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8732 value, sizeof(value));
8733
8734 if (ret >= 0) {
8735 bool vr_audio_enabled = false;
8736 pthread_mutex_lock(&adev->lock);
8737 vr_audio_enabled = adev->vr_audio_mode_enabled;
8738 pthread_mutex_unlock(&adev->lock);
8739
8740 ALOGI("getting vr mode to %d", vr_audio_enabled);
8741
8742 if (vr_audio_enabled) {
8743 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8744 "true");
8745 goto exit;
8746 } else {
8747 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8748 "false");
8749 goto exit;
8750 }
8751 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008752
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008753 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008754 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008755 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008756 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008757 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308758 pthread_mutex_unlock(&adev->lock);
8759
Naresh Tannirud7205b62014-06-20 02:54:48 +05308760exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008761 str = str_parms_to_str(reply);
8762 str_parms_destroy(query);
8763 str_parms_destroy(reply);
8764
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308765 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008766 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008767}
8768
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008769static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008770{
8771 return 0;
8772}
8773
8774static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8775{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008776 int ret;
8777 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008778
8779 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8780
Haynes Mathew George5191a852013-09-11 14:19:36 -07008781 pthread_mutex_lock(&adev->lock);
8782 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008783 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008784 pthread_mutex_unlock(&adev->lock);
8785 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008786}
8787
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008788static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8789 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008790{
8791 return -ENOSYS;
8792}
8793
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008794static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8795 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008796{
8797 return -ENOSYS;
8798}
8799
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008800static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8801 bool muted __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_mute(struct audio_hw_device *dev __unused,
8807 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008808{
8809 return -ENOSYS;
8810}
8811
8812static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8813{
8814 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008815 struct listnode *node;
8816 struct audio_usecase *usecase = NULL;
8817 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008819 pthread_mutex_lock(&adev->lock);
8820 if (adev->mode != mode) {
Jaideep Sharma477917f2020-03-13 18:13:33 +05308821 ALOGD("%s: mode %d , prev_mode %d \n", __func__, mode , adev->mode);
8822 adev->prev_mode = adev->mode; /* prev_mode is kept to handle voip concurrency*/
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008823 adev->mode = mode;
Jaideep Sharma477917f2020-03-13 18:13:33 +05308824 if( mode == AUDIO_MODE_CALL_SCREEN ){
8825 adev->current_call_output = adev->primary_output;
8826 voice_start_call(adev);
8827 } else if (voice_is_in_call_or_call_screen(adev) &&
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008828 (mode == AUDIO_MODE_NORMAL ||
8829 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008830 list_for_each(node, &adev->usecase_list) {
8831 usecase = node_to_item(node, struct audio_usecase, list);
8832 if (usecase->type == VOICE_CALL)
8833 break;
8834 }
8835 if (usecase &&
8836 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8837 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8838 true);
8839 if (ret != 0) {
8840 /* default service interval was successfully updated,
8841 reopen USB backend with new service interval */
8842 check_usecases_codec_backend(adev,
8843 usecase,
8844 usecase->out_snd_device);
8845 }
8846 }
8847
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008848 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008849 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008850 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008851 // restore device for other active usecases after stop call
8852 list_for_each(node, &adev->usecase_list) {
8853 usecase = node_to_item(node, struct audio_usecase, list);
8854 select_devices(adev, usecase->id);
8855 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008856 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008857 }
8858 pthread_mutex_unlock(&adev->lock);
8859 return 0;
8860}
8861
8862static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8863{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008864 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008865 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008866
8867 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008868 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008869 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008870
Derek Chend2530072014-11-24 12:39:14 -08008871 if (adev->ext_hw_plugin)
8872 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008873
8874 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008875 pthread_mutex_unlock(&adev->lock);
8876
8877 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008878}
8879
8880static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8881{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008882 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008883 return 0;
8884}
8885
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008886static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008887 const struct audio_config *config)
8888{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008889 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008890
Aalique Grahame22e49102018-12-18 14:23:57 -08008891 /* Don't know if USB HIFI in this context so use true to be conservative */
8892 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8893 true /*is_usb_hifi */) != 0)
8894 return 0;
8895
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008896 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8897 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008898}
8899
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008900static bool adev_input_allow_hifi_record(struct audio_device *adev,
8901 audio_devices_t devices,
8902 audio_input_flags_t flags,
8903 audio_source_t source) {
8904 const bool allowed = true;
8905
8906 if (!audio_is_usb_in_device(devices))
8907 return !allowed;
8908
8909 switch (flags) {
8910 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008911 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008912 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8913 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008914 default:
8915 return !allowed;
8916 }
8917
8918 switch (source) {
8919 case AUDIO_SOURCE_DEFAULT:
8920 case AUDIO_SOURCE_MIC:
8921 case AUDIO_SOURCE_UNPROCESSED:
8922 break;
8923 default:
8924 return !allowed;
8925 }
8926
8927 switch (adev->mode) {
8928 case 0:
8929 break;
8930 default:
8931 return !allowed;
8932 }
8933
8934 return allowed;
8935}
8936
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008937static int adev_update_voice_comm_input_stream(struct stream_in *in,
8938 struct audio_config *config)
8939{
8940 bool valid_rate = (config->sample_rate == 8000 ||
8941 config->sample_rate == 16000 ||
8942 config->sample_rate == 32000 ||
8943 config->sample_rate == 48000);
8944 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8945
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008946 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008947 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008948 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8949 in->config = default_pcm_config_voip_copp;
8950 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8951 DEFAULT_VOIP_BUF_DURATION_MS,
8952 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008953 } else {
8954 ALOGW("%s No valid input in voip, use defaults"
8955 "sample rate %u, channel mask 0x%X",
8956 __func__, config->sample_rate, in->channel_mask);
8957 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008958 in->config.rate = config->sample_rate;
8959 in->sample_rate = config->sample_rate;
8960 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008961 //XXX needed for voice_extn_compress_voip_open_input_stream
8962 in->config.rate = config->sample_rate;
8963 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathaa763cc42019-08-23 15:13:46 +05308964 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008965 voice_extn_compress_voip_is_active(in->dev)) &&
8966 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8967 valid_rate && valid_ch) {
8968 voice_extn_compress_voip_open_input_stream(in);
8969 // update rate entries to match config from AF
8970 in->config.rate = config->sample_rate;
8971 in->sample_rate = config->sample_rate;
8972 } else {
8973 ALOGW("%s compress voip not active, use defaults", __func__);
8974 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008975 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008976 return 0;
8977}
8978
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008979static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008980 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008981 audio_devices_t devices,
8982 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008983 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308984 audio_input_flags_t flags,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08008985 const char *address,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008986 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008987{
8988 struct audio_device *adev = (struct audio_device *)dev;
8989 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008990 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008991 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008992 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308993 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008994 bool is_usb_dev = audio_is_usb_in_device(devices);
8995 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8996 devices,
8997 flags,
8998 source);
Andy Hung94320602018-10-29 18:31:12 -07008999 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
9000 " sample_rate %u, channel_mask %#x, format %#x",
9001 __func__, flags, is_usb_dev, may_use_hifi_record,
9002 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309003
kunleizdff872d2018-08-20 14:40:33 +08009004 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08009005 is_usb_dev = false;
9006 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
9007 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
9008 __func__, devices);
9009 }
9010
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009011 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009012
9013 if (!(is_usb_dev && may_use_hifi_record)) {
9014 if (config->sample_rate == 0)
9015 config->sample_rate = 48000;
9016 if (config->channel_mask == AUDIO_CHANNEL_NONE)
9017 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9018 if (config->format == AUDIO_FORMAT_DEFAULT)
9019 config->format = AUDIO_FORMAT_PCM_16_BIT;
9020
9021 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
9022
Aalique Grahame22e49102018-12-18 14:23:57 -08009023 if (check_input_parameters(config->sample_rate, config->format, channel_count,
9024 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009025 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05309026 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009027
Rahul Sharma99770982019-03-06 17:05:26 +05309028 pthread_mutex_lock(&adev->lock);
9029 if (in_get_stream(adev, handle) != NULL) {
9030 ALOGW("%s, input stream already opened", __func__);
9031 ret = -EEXIST;
9032 }
9033 pthread_mutex_unlock(&adev->lock);
9034 if (ret)
9035 return ret;
9036
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009037 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009038
9039 if (!in) {
9040 ALOGE("failed to allocate input stream");
9041 return -ENOMEM;
9042 }
9043
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309044 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05309045 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
9046 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009047 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07009048 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009050 in->stream.common.get_sample_rate = in_get_sample_rate;
9051 in->stream.common.set_sample_rate = in_set_sample_rate;
9052 in->stream.common.get_buffer_size = in_get_buffer_size;
9053 in->stream.common.get_channels = in_get_channels;
9054 in->stream.common.get_format = in_get_format;
9055 in->stream.common.set_format = in_set_format;
9056 in->stream.common.standby = in_standby;
9057 in->stream.common.dump = in_dump;
9058 in->stream.common.set_parameters = in_set_parameters;
9059 in->stream.common.get_parameters = in_get_parameters;
9060 in->stream.common.add_audio_effect = in_add_audio_effect;
9061 in->stream.common.remove_audio_effect = in_remove_audio_effect;
9062 in->stream.set_gain = in_set_gain;
9063 in->stream.read = in_read;
9064 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08009065 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309066 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07009067 in->stream.set_microphone_direction = in_set_microphone_direction;
9068 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07009069 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009070
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009071 list_init(&in->device_list);
9072 update_device_list(&in->device_list, devices, address, true);
Vidyakumar Athota5c398212015-03-31 21:53:21 -07009073 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009074 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009075 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009076 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009077 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07009078 in->bit_width = 16;
9079 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07009080 in->direction = MIC_DIRECTION_UNSPECIFIED;
9081 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08009082 list_init(&in->aec_list);
9083 list_init(&in->ns_list);
Phil Burkd898ba62019-06-20 12:49:01 -07009084 in->mmap_shared_memory_fd = -1; // not open
Haynes Mathew George46740472017-10-27 18:40:12 -07009085
Andy Hung94320602018-10-29 18:31:12 -07009086 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08009087 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
9088 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
9089 /* Force channel config requested to mono if incall
9090 record is being requested for only uplink/downlink */
9091 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
9092 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
9093 ret = -EINVAL;
9094 goto err_open;
9095 }
9096 }
9097
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009098 if (is_usb_dev && may_use_hifi_record) {
9099 /* HiFi record selects an appropriate format, channel, rate combo
9100 depending on sink capabilities*/
9101 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
9102 &config->format,
9103 &in->supported_formats[0],
9104 MAX_SUPPORTED_FORMATS,
9105 &config->channel_mask,
9106 &in->supported_channel_masks[0],
9107 MAX_SUPPORTED_CHANNEL_MASKS,
9108 &config->sample_rate,
9109 &in->supported_sample_rates[0],
9110 MAX_SUPPORTED_SAMPLE_RATES);
9111 if (ret != 0) {
9112 ret = -EINVAL;
9113 goto err_open;
9114 }
9115 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009116 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309117 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05309118 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
9119 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
9120 in->config.format = PCM_FORMAT_S32_LE;
9121 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309122 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
9123 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
9124 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
9125 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
9126 bool ret_error = false;
9127 in->bit_width = 24;
9128 /* 24 bit is restricted to UNPROCESSED source only,also format supported
9129 from HAL is 24_packed and 8_24
9130 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
9131 24_packed return error indicating supported format is 24_packed
9132 *> In case of any other source requesting 24 bit or float return error
9133 indicating format supported is 16 bit only.
9134
9135 on error flinger will retry with supported format passed
9136 */
9137 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
9138 (source != AUDIO_SOURCE_CAMCORDER)) {
9139 config->format = AUDIO_FORMAT_PCM_16_BIT;
9140 if (config->sample_rate > 48000)
9141 config->sample_rate = 48000;
9142 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07009143 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
9144 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309145 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
9146 ret_error = true;
9147 }
9148
9149 if (ret_error) {
9150 ret = -EINVAL;
9151 goto err_open;
9152 }
9153 }
9154
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009155 in->channel_mask = config->channel_mask;
9156 in->format = config->format;
9157
9158 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05309159
9160 if (in->source == AUDIO_SOURCE_FM_TUNER) {
9161 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
9162 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
9163 else {
9164 ret = -EINVAL;
9165 goto err_open;
9166 }
9167 }
9168
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009169 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05309170 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
9171 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009172 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
9173 is_low_latency = true;
9174#if LOW_LATENCY_CAPTURE_USE_CASE
9175 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
9176#endif
9177 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08009178 if (!in->realtime) {
9179 in->config = pcm_config_audio_capture;
9180 frame_size = audio_stream_in_frame_size(&in->stream);
9181 buffer_size = get_input_buffer_size(config->sample_rate,
9182 config->format,
9183 channel_count,
9184 is_low_latency);
9185 in->config.period_size = buffer_size / frame_size;
9186 in->config.rate = config->sample_rate;
9187 in->af_period_multiplier = 1;
9188 } else {
9189 // period size is left untouched for rt mode playback
9190 in->config = pcm_config_audio_capture_rt;
9191 in->af_period_multiplier = af_period_multiplier;
9192 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009193 }
9194
9195 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
9196 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
9197 in->realtime = 0;
9198 in->usecase = USECASE_AUDIO_RECORD_MMAP;
9199 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07009200 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009201 in->stream.start = in_start;
9202 in->stream.stop = in_stop;
9203 in->stream.create_mmap_buffer = in_create_mmap_buffer;
9204 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009205 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
9206 } else if (in->realtime) {
9207 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07009208 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009209 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07009210 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009211 in->usecase = USECASE_AUDIO_RECORD_HIFI;
9212 in->config = pcm_config_audio_capture;
9213 frame_size = audio_stream_in_frame_size(&in->stream);
9214 buffer_size = get_input_buffer_size(config->sample_rate,
9215 config->format,
9216 channel_count,
9217 false /*is_low_latency*/);
9218 in->config.period_size = buffer_size / frame_size;
9219 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07009220 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07009221 switch (config->format) {
9222 case AUDIO_FORMAT_PCM_32_BIT:
9223 in->bit_width = 32;
9224 break;
9225 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
9226 case AUDIO_FORMAT_PCM_8_24_BIT:
9227 in->bit_width = 24;
9228 break;
9229 default:
9230 in->bit_width = 16;
9231 }
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009232 } else if (is_single_device_type_equal(&in->device_list,
9233 AUDIO_DEVICE_IN_TELEPHONY_RX) ||
9234 is_single_device_type_equal(&in->device_list,
9235 AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009236 if (config->sample_rate == 0)
9237 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9238 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
9239 config->sample_rate != 8000) {
9240 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
9241 ret = -EINVAL;
9242 goto err_open;
9243 }
9244 if (config->format == AUDIO_FORMAT_DEFAULT)
9245 config->format = AUDIO_FORMAT_PCM_16_BIT;
9246 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
9247 config->format = AUDIO_FORMAT_PCM_16_BIT;
9248 ret = -EINVAL;
9249 goto err_open;
9250 }
9251
9252 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
9253 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07009254 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08009255 in->af_period_multiplier = 1;
9256 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
9257 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
9258 (config->sample_rate == 8000 ||
9259 config->sample_rate == 16000 ||
9260 config->sample_rate == 32000 ||
9261 config->sample_rate == 48000) &&
9262 channel_count == 1) {
9263 in->usecase = USECASE_AUDIO_RECORD_VOIP;
9264 in->config = pcm_config_audio_capture;
9265 frame_size = audio_stream_in_frame_size(&in->stream);
9266 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
9267 config->sample_rate,
9268 config->format,
9269 channel_count, false /*is_low_latency*/);
9270 in->config.period_size = buffer_size / frame_size;
9271 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
9272 in->config.rate = config->sample_rate;
9273 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07009274 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05309275 int ret_val;
9276 pthread_mutex_lock(&adev->lock);
9277 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
9278 in, config, &channel_mask_updated);
9279 pthread_mutex_unlock(&adev->lock);
9280
9281 if (!ret_val) {
9282 if (channel_mask_updated == true) {
9283 ALOGD("%s: return error to retry with updated channel mask (%#x)",
9284 __func__, config->channel_mask);
9285 ret = -EINVAL;
9286 goto err_open;
9287 }
9288 ALOGD("%s: created multi-channel session succesfully",__func__);
9289 } else if (audio_extn_compr_cap_enabled() &&
9290 audio_extn_compr_cap_format_supported(config->format) &&
9291 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
9292 audio_extn_compr_cap_init(in);
9293 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05309294 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309295 if (ret)
9296 goto err_open;
9297 } else {
9298 in->config = pcm_config_audio_capture;
9299 in->config.rate = config->sample_rate;
9300 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309301 in->format = config->format;
9302 frame_size = audio_stream_in_frame_size(&in->stream);
9303 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009304 config->format,
9305 channel_count,
9306 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009307 /* prevent division-by-zero */
9308 if (frame_size == 0) {
9309 ALOGE("%s: Error frame_size==0", __func__);
9310 ret = -EINVAL;
9311 goto err_open;
9312 }
9313
Revathi Uddarajud2634032017-12-07 14:42:34 +05309314 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009315 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009316
Revathi Uddarajud2634032017-12-07 14:42:34 +05309317 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9318 /* optionally use VOIP usecase depending on config(s) */
9319 ret = adev_update_voice_comm_input_stream(in, config);
9320 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009321
Revathi Uddarajud2634032017-12-07 14:42:34 +05309322 if (ret) {
9323 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9324 goto err_open;
9325 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009326 }
Jaideep Sharmad305a4a2020-02-27 14:29:04 +05309327
9328 /* assign concurrent capture usecase if record has to caried out from
9329 * actual hardware input source */
9330 if (audio_extn_is_concurrent_capture_enabled() &&
9331 !audio_is_virtual_input_source(in->source)) {
Samyak Jainc37062f2019-04-25 18:41:06 +05309332 /* Acquire lock to avoid two concurrent use cases initialized to
9333 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009334
Samyak Jainc37062f2019-04-25 18:41:06 +05309335 if (in->usecase == USECASE_AUDIO_RECORD) {
9336 pthread_mutex_lock(&adev->lock);
9337 if (!(adev->pcm_record_uc_state)) {
9338 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9339 adev->pcm_record_uc_state = 1;
9340 pthread_mutex_unlock(&adev->lock);
9341 } else {
9342 pthread_mutex_unlock(&adev->lock);
9343 /* Assign compress record use case for second record */
9344 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9345 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9346 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9347 if (audio_extn_cin_applicable_stream(in)) {
9348 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309349 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309350 if (ret)
9351 goto err_open;
9352 }
9353 }
9354 }
kunleiz28c73e72019-03-27 17:24:04 +08009355 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009356 }
Ramjee Singh82fd0c12019-08-21 16:31:33 +05309357 if (audio_extn_ssr_get_stream() != in)
9358 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009359
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009360 in->sample_rate = in->config.rate;
9361
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309362 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9363 &adev->streams_input_cfg_list,
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009364 &in->device_list, flags, in->format,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009365 in->sample_rate, in->bit_width,
9366 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309367 register_format(in->format, in->supported_formats);
9368 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9369 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309370
Aalique Grahame22e49102018-12-18 14:23:57 -08009371 in->error_log = error_log_create(
9372 ERROR_LOG_ENTRIES,
9373 1000000000 /* aggregate consecutive identical errors within one second */);
9374
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009375 /* This stream could be for sound trigger lab,
9376 get sound trigger pcm if present */
9377 audio_extn_sound_trigger_check_and_get_session(in);
9378
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309379 lock_input_stream(in);
9380 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9381 pthread_mutex_lock(&adev->lock);
9382 in->card_status = adev->card_status;
9383 pthread_mutex_unlock(&adev->lock);
9384 pthread_mutex_unlock(&in->lock);
9385
Aalique Grahame22e49102018-12-18 14:23:57 -08009386 stream_app_type_cfg_init(&in->app_type_cfg);
9387
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009388 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009389
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009390 ret = io_streams_map_insert(adev, &in->stream.common,
9391 handle, AUDIO_PATCH_HANDLE_NONE);
9392 if (ret != 0)
9393 goto err_open;
9394
Derek Chenf939fb72018-11-13 13:34:41 -08009395 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9396 calloc(1, sizeof(streams_input_ctxt_t));
9397 if (in_ctxt == NULL) {
9398 ALOGE("%s fail to allocate input ctxt", __func__);
9399 ret = -ENOMEM;
9400 goto err_open;
9401 }
9402 in_ctxt->input = in;
9403
9404 pthread_mutex_lock(&adev->lock);
9405 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9406 pthread_mutex_unlock(&adev->lock);
9407
Eric Laurent994a6932013-07-17 11:51:42 -07009408 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009409 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009410
9411err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309412 if (in->usecase == USECASE_AUDIO_RECORD) {
9413 pthread_mutex_lock(&adev->lock);
9414 adev->pcm_record_uc_state = 0;
9415 pthread_mutex_unlock(&adev->lock);
9416 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009417 free(in);
9418 *stream_in = NULL;
9419 return ret;
9420}
9421
9422static void adev_close_input_stream(struct audio_hw_device *dev,
9423 struct audio_stream_in *stream)
9424{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009425 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009426 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009427 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309428
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309429 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009430
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009431 if (in == NULL) {
9432 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9433 return;
9434 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009435 io_streams_map_remove(adev, in->capture_handle);
9436
kunleiz70e57612018-12-28 17:50:23 +08009437 /* must deregister from sndmonitor first to prevent races
9438 * between the callback and close_stream
9439 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309440 audio_extn_snd_mon_unregister_listener(stream);
9441
kunleiz70e57612018-12-28 17:50:23 +08009442 /* Disable echo reference if there are no active input, hfp call
9443 * and sound trigger while closing input stream
9444 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009445 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009446 !audio_extn_hfp_is_active(adev) &&
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009447 !audio_extn_sound_trigger_check_ec_ref_enable()) {
9448 struct listnode out_devices;
9449 list_init(&out_devices);
9450 platform_set_echo_reference(adev, false, &out_devices);
9451 } else
kunleiz70e57612018-12-28 17:50:23 +08009452 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309453
Weiyin Jiang2995f662019-04-17 14:25:12 +08009454 error_log_destroy(in->error_log);
9455 in->error_log = NULL;
9456
Pallavid7c7a272018-01-16 11:22:55 +05309457
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009458 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309459 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009460 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309461 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009462 if (ret != 0)
9463 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9464 __func__, ret);
9465 } else
9466 in_standby(&stream->common);
9467
Revathi Uddarajud2634032017-12-07 14:42:34 +05309468 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309469 if (in->usecase == USECASE_AUDIO_RECORD) {
9470 adev->pcm_record_uc_state = 0;
9471 }
9472
Kunlei Zhang5d5d8d92020-02-26 15:00:59 +08009473 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9474 adev->enable_voicerx = false;
9475 }
9476
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009477 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009478 audio_extn_ssr_deinit();
9479 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009480
Garmond Leunge2433c32017-09-28 21:51:22 -07009481 if (audio_extn_ffv_get_stream() == in) {
9482 audio_extn_ffv_stream_deinit();
9483 }
9484
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309485 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009486 audio_extn_compr_cap_format_supported(in->config.format))
9487 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309488
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309489 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05309490 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009491
Mingming Yinfd7607b2016-01-22 12:48:44 -08009492 if (in->is_st_session) {
9493 ALOGV("%s: sound trigger pcm stop lab", __func__);
9494 audio_extn_sound_trigger_stop_lab(in);
9495 }
Derek Chenf939fb72018-11-13 13:34:41 -08009496 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9497 if (in_ctxt != NULL) {
9498 list_remove(&in_ctxt->list);
9499 free(in_ctxt);
9500 } else {
9501 ALOGW("%s, input stream already closed", __func__);
9502 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009503 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309504 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009505 return;
9506}
9507
Aalique Grahame22e49102018-12-18 14:23:57 -08009508/* verifies input and output devices and their capabilities.
9509 *
9510 * This verification is required when enabling extended bit-depth or
9511 * sampling rates, as not all qcom products support it.
9512 *
9513 * Suitable for calling only on initialization such as adev_open().
9514 * It fills the audio_device use_case_table[] array.
9515 *
9516 * Has a side-effect that it needs to configure audio routing / devices
9517 * in order to power up the devices and read the device parameters.
9518 * It does not acquire any hw device lock. Should restore the devices
9519 * back to "normal state" upon completion.
9520 */
9521static int adev_verify_devices(struct audio_device *adev)
9522{
9523 /* enumeration is a bit difficult because one really wants to pull
9524 * the use_case, device id, etc from the hidden pcm_device_table[].
9525 * In this case there are the following use cases and device ids.
9526 *
9527 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9528 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9529 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9530 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9531 * [USECASE_AUDIO_RECORD] = {0, 0},
9532 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9533 * [USECASE_VOICE_CALL] = {2, 2},
9534 *
9535 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9536 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9537 */
9538
9539 /* should be the usecases enabled in adev_open_input_stream() */
9540 static const int test_in_usecases[] = {
9541 USECASE_AUDIO_RECORD,
9542 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9543 };
9544 /* should be the usecases enabled in adev_open_output_stream()*/
9545 static const int test_out_usecases[] = {
9546 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9547 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9548 };
9549 static const usecase_type_t usecase_type_by_dir[] = {
9550 PCM_PLAYBACK,
9551 PCM_CAPTURE,
9552 };
9553 static const unsigned flags_by_dir[] = {
9554 PCM_OUT,
9555 PCM_IN,
9556 };
9557
9558 size_t i;
9559 unsigned dir;
9560 const unsigned card_id = adev->snd_card;
9561
9562 for (dir = 0; dir < 2; ++dir) {
9563 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9564 const unsigned flags_dir = flags_by_dir[dir];
9565 const size_t testsize =
9566 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9567 const int *testcases =
9568 dir ? test_in_usecases : test_out_usecases;
9569 const audio_devices_t audio_device =
9570 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9571
9572 for (i = 0; i < testsize; ++i) {
9573 const audio_usecase_t audio_usecase = testcases[i];
9574 int device_id;
9575 struct pcm_params **pparams;
9576 struct stream_out out;
9577 struct stream_in in;
9578 struct audio_usecase uc_info;
9579 int retval;
9580
9581 pparams = &adev->use_case_table[audio_usecase];
9582 pcm_params_free(*pparams); /* can accept null input */
9583 *pparams = NULL;
9584
9585 /* find the device ID for the use case (signed, for error) */
9586 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9587 if (device_id < 0)
9588 continue;
9589
9590 /* prepare structures for device probing */
9591 memset(&uc_info, 0, sizeof(uc_info));
9592 uc_info.id = audio_usecase;
9593 uc_info.type = usecase_type;
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009594 list_init(&uc_info.device_list);
Aalique Grahame22e49102018-12-18 14:23:57 -08009595 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009596 memset(&in, 0, sizeof(in));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009597 list_init(&in.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009598 update_device_list(&in.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009599 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9600 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009601 }
9602 memset(&out, 0, sizeof(out));
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -08009603 list_init(&out.device_list);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009604 update_device_list(&out.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009605 uc_info.stream.out = &out;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009606 update_device_list(&uc_info.device_list, audio_device, "", true);
Aalique Grahame22e49102018-12-18 14:23:57 -08009607 uc_info.in_snd_device = SND_DEVICE_NONE;
9608 uc_info.out_snd_device = SND_DEVICE_NONE;
9609 list_add_tail(&adev->usecase_list, &uc_info.list);
9610
9611 /* select device - similar to start_(in/out)put_stream() */
9612 retval = select_devices(adev, audio_usecase);
9613 if (retval >= 0) {
9614 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9615#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009616 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009617 if (*pparams) {
9618 ALOGV("%s: (%s) card %d device %d", __func__,
9619 dir ? "input" : "output", card_id, device_id);
9620 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9621 } else {
9622 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9623 }
9624#endif
9625 }
9626
9627 /* deselect device - similar to stop_(in/out)put_stream() */
9628 /* 1. Get and set stream specific mixer controls */
9629 retval = disable_audio_route(adev, &uc_info);
9630 /* 2. Disable the rx device */
9631 retval = disable_snd_device(adev,
9632 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9633 list_remove(&uc_info.list);
9634 }
9635 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009636 return 0;
9637}
9638
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009639int update_patch(unsigned int num_sources,
9640 const struct audio_port_config *sources,
9641 unsigned int num_sinks,
9642 const struct audio_port_config *sinks,
9643 audio_patch_handle_t handle,
9644 struct audio_patch_info *p_info,
9645 patch_type_t patch_type, bool new_patch)
9646{
9647 ALOGD("%s: enter", __func__);
9648
9649 if (p_info == NULL) {
9650 ALOGE("%s: Invalid patch pointer", __func__);
9651 return -EINVAL;
9652 }
9653
9654 if (new_patch) {
9655 p_info->patch = (struct audio_patch *) calloc(1, sizeof(struct audio_patch));
9656 if (p_info->patch == NULL) {
9657 ALOGE("%s: Could not allocate patch", __func__);
9658 return -ENOMEM;
9659 }
9660 }
9661
9662 p_info->patch->id = handle;
9663 p_info->patch->num_sources = num_sources;
9664 p_info->patch->num_sinks = num_sinks;
9665
9666 for (int i = 0; i < num_sources; i++)
9667 p_info->patch->sources[i] = sources[i];
9668 for (int i = 0; i < num_sinks; i++)
9669 p_info->patch->sinks[i] = sinks[i];
9670
9671 p_info->patch_type = patch_type;
9672 return 0;
9673}
9674
9675audio_patch_handle_t generate_patch_handle()
9676{
9677 static audio_patch_handle_t patch_handle = AUDIO_PATCH_HANDLE_NONE;
9678 if (++patch_handle < 0)
9679 patch_handle = AUDIO_PATCH_HANDLE_NONE + 1;
9680 return patch_handle;
9681}
9682
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309683int adev_create_audio_patch(struct audio_hw_device *dev,
9684 unsigned int num_sources,
9685 const struct audio_port_config *sources,
9686 unsigned int num_sinks,
9687 const struct audio_port_config *sinks,
9688 audio_patch_handle_t *handle)
9689{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009690 int ret = 0;
9691 struct audio_device *adev = (struct audio_device *)dev;
9692 struct audio_patch_info *p_info = NULL;
9693 patch_type_t patch_type = PATCH_NONE;
9694 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9695 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
9696 struct audio_stream_info *s_info = NULL;
9697 struct audio_stream *stream = NULL;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009698 struct listnode devices;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009699 audio_devices_t device_type = AUDIO_DEVICE_NONE;
9700 bool new_patch = false;
9701 char addr[AUDIO_DEVICE_MAX_ADDRESS_LEN];
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309702
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009703 ALOGD("%s: enter: num sources %d, num_sinks %d, handle %d", __func__,
9704 num_sources, num_sinks, *handle);
9705
9706 if (num_sources == 0 || num_sources > AUDIO_PATCH_PORTS_MAX ||
9707 num_sinks == 0 || num_sinks > AUDIO_PATCH_PORTS_MAX) {
9708 ALOGE("%s: Invalid patch arguments", __func__);
9709 ret = -EINVAL;
9710 goto done;
9711 }
9712
9713 if (num_sources > 1) {
9714 ALOGE("%s: Multiple sources are not supported", __func__);
9715 ret = -EINVAL;
9716 goto done;
9717 }
9718
9719 if (sources == NULL || sinks == NULL) {
9720 ALOGE("%s: Invalid sources or sinks port config", __func__);
9721 ret = -EINVAL;
9722 goto done;
9723 }
9724
9725 ALOGV("%s: source role %d, source type %d", __func__,
9726 sources[0].type, sources[0].role);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009727 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009728
9729 // Populate source/sink information and fetch stream info
9730 switch (sources[0].type) {
9731 case AUDIO_PORT_TYPE_DEVICE: // Patch for audio capture or loopback
9732 device_type = sources[0].ext.device.type;
9733 strlcpy(&addr[0], &sources[0].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009734 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009735 if (sinks[0].type == AUDIO_PORT_TYPE_MIX) {
9736 patch_type = PATCH_CAPTURE;
9737 io_handle = sinks[0].ext.mix.handle;
9738 input_source = sinks[0].ext.mix.usecase.source;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009739 ALOGD("%s: Capture patch from device %x to mix %d",
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009740 __func__, device_type, io_handle);
9741 } else {
9742 // Device to device patch is not implemented.
9743 // This space will need changes if audio HAL
9744 // handles device to device patches in the future.
9745 patch_type = PATCH_DEVICE_LOOPBACK;
9746 }
9747 break;
9748 case AUDIO_PORT_TYPE_MIX: // Patch for audio playback
9749 io_handle = sources[0].ext.mix.handle;
9750 for (int i = 0; i < num_sinks; i++) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009751 device_type = sinks[i].ext.device.type;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009752 strlcpy(&addr[0], &sinks[i].ext.device.address[0], AUDIO_DEVICE_MAX_ADDRESS_LEN);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009753 update_device_list(&devices, device_type, &addr[0], true);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009754 }
9755 patch_type = PATCH_PLAYBACK;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009756 ALOGD("%s: Playback patch from mix handle %d to device %x",
9757 __func__, io_handle, get_device_types(&devices));
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009758 break;
9759 case AUDIO_PORT_TYPE_SESSION:
9760 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009761 ALOGE("%s: Unsupported source type %d", __func__, sources[0].type);
9762 ret = -EINVAL;
9763 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009764 }
9765
9766 pthread_mutex_lock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009767
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009768 // Generate patch info and update patch
9769 if (*handle == AUDIO_PATCH_HANDLE_NONE) {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009770 *handle = generate_patch_handle();
9771 p_info = (struct audio_patch_info *)
9772 calloc(1, sizeof(struct audio_patch_info));
9773 if (p_info == NULL) {
9774 ALOGE("%s: Failed to allocate memory", __func__);
9775 pthread_mutex_unlock(&adev->lock);
9776 ret = -ENOMEM;
9777 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009778 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009779 new_patch = true;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009780 } else {
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009781 p_info = fetch_patch_info_l(adev, *handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009782 if (p_info == NULL) {
9783 ALOGE("%s: Unable to fetch patch for received patch handle %d",
9784 __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009785 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009786 ret = -EINVAL;
9787 goto done;
9788 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009789 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009790 update_patch(num_sources, sources, num_sinks, sinks,
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009791 *handle, p_info, patch_type, new_patch);
9792
9793 // Fetch stream info of associated mix for playback or capture patches
9794 if (p_info->patch_type == PATCH_PLAYBACK ||
9795 p_info->patch_type == PATCH_CAPTURE) {
9796 s_info = hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9797 if (s_info == NULL) {
9798 ALOGE("%s: Failed to obtain stream info", __func__);
9799 if (new_patch)
9800 free(p_info);
9801 pthread_mutex_unlock(&adev->lock);
9802 ret = -EINVAL;
9803 goto done;
9804 }
9805 ALOGV("%s: Fetched stream info with io_handle %d", __func__, io_handle);
9806 s_info->patch_handle = *handle;
9807 stream = s_info->stream;
9808 }
9809 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009810
9811 // Update routing for stream
9812 if (stream != NULL) {
9813 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009814 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009815 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009816 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009817 if (ret < 0) {
9818 pthread_mutex_lock(&adev->lock);
9819 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9820 if (new_patch)
9821 free(p_info);
9822 pthread_mutex_unlock(&adev->lock);
9823 ALOGE("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9824 goto done;
9825 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009826 }
9827
9828 // Add new patch to patch map
9829 if (!ret && new_patch) {
9830 pthread_mutex_lock(&adev->lock);
9831 hashmapPut(adev->patch_map, (void *) (intptr_t) *handle, (void *) p_info);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009832 ALOGD("%s: Added a new patch with handle %d", __func__, *handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009833 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009834 }
9835
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009836done:
9837 audio_extn_hw_loopback_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009838 num_sources,
9839 sources,
9840 num_sinks,
9841 sinks,
9842 handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009843 audio_extn_auto_hal_create_audio_patch(dev,
Derek Chenf939fb72018-11-13 13:34:41 -08009844 num_sources,
9845 sources,
9846 num_sinks,
9847 sinks,
9848 handle);
9849 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309850}
9851
9852int adev_release_audio_patch(struct audio_hw_device *dev,
9853 audio_patch_handle_t handle)
9854{
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009855 struct audio_device *adev = (struct audio_device *) dev;
9856 int ret = 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009857 audio_source_t input_source = AUDIO_SOURCE_DEFAULT;
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009858 struct audio_stream *stream = NULL;
Derek Chenf939fb72018-11-13 13:34:41 -08009859
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009860 if (handle == AUDIO_PATCH_HANDLE_NONE) {
9861 ALOGE("%s: Invalid patch handle %d", __func__, handle);
9862 ret = -EINVAL;
9863 goto done;
9864 }
9865
9866 ALOGD("%s: Remove patch with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009867 pthread_mutex_lock(&adev->lock);
9868 struct audio_patch_info *p_info = fetch_patch_info_l(adev, handle);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009869 if (p_info == NULL) {
9870 ALOGE("%s: Patch info not found with handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009871 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009872 ret = -EINVAL;
9873 goto done;
9874 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009875 struct audio_patch *patch = p_info->patch;
9876 if (patch == NULL) {
9877 ALOGE("%s: Patch not found for handle %d", __func__, handle);
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009878 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009879 ret = -EINVAL;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009880 goto done;
9881 }
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009882 audio_io_handle_t io_handle = AUDIO_IO_HANDLE_NONE;
9883 switch (patch->sources[0].type) {
9884 case AUDIO_PORT_TYPE_MIX:
9885 io_handle = patch->sources[0].ext.mix.handle;
9886 break;
9887 case AUDIO_PORT_TYPE_DEVICE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009888 if (p_info->patch_type == PATCH_CAPTURE)
9889 io_handle = patch->sinks[0].ext.mix.handle;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009890 break;
9891 case AUDIO_PORT_TYPE_SESSION:
9892 case AUDIO_PORT_TYPE_NONE:
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009893 pthread_mutex_unlock(&adev->lock);
9894 ret = -EINVAL;
9895 goto done;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009896 }
9897
9898 // Remove patch and reset patch handle in stream info
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009899 patch_map_remove_l(adev, handle);
9900 if (p_info->patch_type == PATCH_PLAYBACK ||
9901 p_info->patch_type == PATCH_CAPTURE) {
9902 struct audio_stream_info *s_info =
9903 hashmapGet(adev->io_streams_map, (void *) (intptr_t) io_handle);
9904 if (s_info == NULL) {
9905 ALOGE("%s: stream for io_handle %d is not available", __func__, io_handle);
9906 pthread_mutex_unlock(&adev->lock);
9907 goto done;
9908 }
9909 s_info->patch_handle = AUDIO_PATCH_HANDLE_NONE;
9910 stream = s_info->stream;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009911 }
Aniket Kumar Latabc774842020-01-16 21:22:05 -08009912 pthread_mutex_unlock(&adev->lock);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009913
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009914 if (stream != NULL) {
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009915 struct listnode devices;
9916 list_init(&devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009917 if (p_info->patch_type == PATCH_PLAYBACK)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009918 ret = route_output_stream((struct stream_out *) stream, &devices);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009919 else if (p_info->patch_type == PATCH_CAPTURE)
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -08009920 ret = route_input_stream((struct stream_in *) stream, &devices, input_source);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009921 }
9922
9923 if (ret < 0)
9924 ALOGW("%s: Stream routing failed for io_handle %d", __func__, io_handle);
9925
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -07009926done:
9927 audio_extn_hw_loopback_release_audio_patch(dev, handle);
9928 audio_extn_auto_hal_release_audio_patch(dev, handle);
9929
9930 ALOGV("%s: Successfully released patch %d", __func__, handle);
Derek Chenf939fb72018-11-13 13:34:41 -08009931 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309932}
9933
9934int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9935{
Derek Chenf13dd492018-11-13 14:53:51 -08009936 int ret = 0;
9937
9938 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9939 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9940 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309941}
9942
9943int adev_set_audio_port_config(struct audio_hw_device *dev,
9944 const struct audio_port_config *config)
9945{
Derek Chenf13dd492018-11-13 14:53:51 -08009946 int ret = 0;
9947
9948 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9949 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9950 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309951}
9952
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009953static int adev_dump(const audio_hw_device_t *device __unused,
9954 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009955{
9956 return 0;
9957}
9958
9959static int adev_close(hw_device_t *device)
9960{
Aalique Grahame22e49102018-12-18 14:23:57 -08009961 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309962 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009963
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309964 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009965 return 0;
9966
9967 pthread_mutex_lock(&adev_init_lock);
9968
9969 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309970 if (audio_extn_spkr_prot_is_enabled())
9971 audio_extn_spkr_prot_deinit();
Jaideep Sharmaa2b49672019-09-10 20:37:03 +05309972 audio_extn_battery_properties_listener_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309973 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009974 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009975 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009976 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009977 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309978 audio_extn_utils_release_streams_cfg_lists(
9979 &adev->streams_output_cfg_list,
9980 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309981 if (audio_extn_qap_is_enabled())
9982 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309983 if (audio_extn_qaf_is_enabled())
9984 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009985 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009986 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009987 free(adev->snd_dev_ref_cnt);
9988 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009989 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9990 pcm_params_free(adev->use_case_table[i]);
9991 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009992 if (adev->adm_deinit)
9993 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309994 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009995 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309996 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309997 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009998 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309999 if (adev->device_cfg_params) {
10000 free(adev->device_cfg_params);
10001 adev->device_cfg_params = NULL;
10002 }
Derek Chend2530072014-11-24 12:39:14 -080010003 if(adev->ext_hw_plugin)
10004 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -080010005 audio_extn_auto_hal_deinit();
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010006 free_map(adev->patch_map);
10007 free_map(adev->io_streams_map);
Kiran Kandi910e1862013-10-29 13:29:42 -070010008 free(device);
10009 adev = NULL;
10010 }
10011 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +053010012 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010013 return 0;
10014}
10015
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010016/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
10017 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
10018 * just that it _might_ work.
10019 */
10020static int period_size_is_plausible_for_low_latency(int period_size)
10021{
10022 switch (period_size) {
10023 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -070010024 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010025 case 240:
10026 case 320:
10027 case 480:
10028 return 1;
10029 default:
10030 return 0;
10031 }
10032}
10033
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010034static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
10035{
10036 bool is_snd_card_status = false;
10037 bool is_ext_device_status = false;
10038 char value[32];
10039 int card = -1;
10040 card_status_t status;
10041
10042 if (cookie != adev || !parms)
10043 return;
10044
10045 if (!parse_snd_card_status(parms, &card, &status)) {
10046 is_snd_card_status = true;
10047 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
10048 is_ext_device_status = true;
10049 } else {
10050 // not a valid event
10051 return;
10052 }
10053
10054 pthread_mutex_lock(&adev->lock);
10055 if (card == adev->snd_card || is_ext_device_status) {
10056 if (is_snd_card_status && adev->card_status != status) {
10057 adev->card_status = status;
10058 platform_snd_card_update(adev->platform, status);
10059 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -080010060 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song4f43e352019-07-02 00:32:23 +080010061 if (status == CARD_STATUS_OFFLINE)
10062 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010063 } else if (is_ext_device_status) {
10064 platform_set_parameters(adev->platform, parms);
10065 }
10066 }
10067 pthread_mutex_unlock(&adev->lock);
10068 return;
10069}
10070
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010071/* out and adev lock held */
10072static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
10073{
10074 struct audio_usecase *uc_info;
10075 float left_p;
10076 float right_p;
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010077 struct listnode devices;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010078
10079 uc_info = get_usecase_from_list(adev, out->usecase);
10080 if (uc_info == NULL) {
10081 ALOGE("%s: Could not find the usecase (%d) in the list",
10082 __func__, out->usecase);
10083 return -EINVAL;
10084 }
Aniket Kumar Lata9c2fd892020-01-22 22:20:00 -080010085 list_init(&devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010086
10087 ALOGD("%s: enter: usecase(%d: %s)", __func__,
10088 out->usecase, use_case_table[out->usecase]);
10089
10090 if (restore) {
10091 // restore A2DP device for active usecases and unmute if required
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010092 if (is_a2dp_out_device_type(&out->device_list)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010093 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
Zhou Songe5225132019-09-26 15:33:36 +080010094 if (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)
10095 select_devices(adev, uc_info->id);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010096 pthread_mutex_lock(&out->compr_mute_lock);
10097 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +053010098 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010099 out->a2dp_compress_mute = false;
10100 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
10101 }
10102 pthread_mutex_unlock(&out->compr_mute_lock);
10103 }
10104 } else {
Zhou Songc576a452019-09-09 14:17:40 +080010105 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10106 // mute compress stream if suspended
10107 pthread_mutex_lock(&out->compr_mute_lock);
10108 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010109 ALOGD("%s: selecting speaker and muting stream", __func__);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010110 assign_devices(&devices, &out->device_list);
10111 reassign_device_list(&out->device_list, AUDIO_DEVICE_OUT_SPEAKER, "");
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010112 left_p = out->volume_l;
10113 right_p = out->volume_r;
10114 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10115 compress_pause(out->compr);
10116 out_set_compr_volume(&out->stream, (float)0, (float)0);
10117 out->a2dp_compress_mute = true;
10118 select_devices(adev, out->usecase);
10119 if (out->offload_state == OFFLOAD_STATE_PLAYING)
10120 compress_resume(out->compr);
Aniket Kumar Lata0e6e1e52019-11-14 21:43:55 -080010121 assign_devices(&out->device_list, &devices);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010122 out->volume_l = left_p;
10123 out->volume_r = right_p;
10124 }
Zhou Songc576a452019-09-09 14:17:40 +080010125 pthread_mutex_unlock(&out->compr_mute_lock);
10126 } else {
10127 // tear down a2dp path for non offloaded streams
10128 if (audio_extn_a2dp_source_is_suspended())
10129 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010130 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +053010131 }
10132 ALOGV("%s: exit", __func__);
10133 return 0;
10134}
10135
10136int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
10137{
10138 int ret = 0;
10139
10140 lock_output_stream(out);
10141 pthread_mutex_lock(&adev->lock);
10142
10143 ret = check_a2dp_restore_l(adev, out, restore);
10144
10145 pthread_mutex_unlock(&adev->lock);
10146 pthread_mutex_unlock(&out->lock);
10147 return ret;
10148}
10149
Haynes Mathew George01156f92018-04-13 15:29:54 -070010150void adev_on_battery_status_changed(bool charging)
10151{
10152 pthread_mutex_lock(&adev->lock);
10153 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
10154 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +080010155 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -070010156 pthread_mutex_unlock(&adev->lock);
10157}
10158
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010159static int adev_open(const hw_module_t *module, const char *name,
10160 hw_device_t **device)
10161{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010162 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -080010163 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010164 char mixer_ctl_name[128] = {0};
10165 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010166
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -080010167 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010168 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
10169
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010170 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -070010171 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010172 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -070010173 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010174 ALOGD("%s: returning existing instance of adev", __func__);
10175 ALOGD("%s: exit", __func__);
10176 pthread_mutex_unlock(&adev_init_lock);
10177 return 0;
10178 }
10179
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010180 adev = calloc(1, sizeof(struct audio_device));
10181
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -070010182 if (!adev) {
10183 pthread_mutex_unlock(&adev_init_lock);
10184 return -ENOMEM;
10185 }
10186
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -070010187 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
10188
Weiyin Jiange6ce6312019-01-28 18:28:22 +080010189 // register audio ext hidl at the earliest
10190 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053010191#ifdef DYNAMIC_LOG_ENABLED
10192 register_for_dynamic_logging("hal");
10193#endif
10194
Derek Chenf939fb72018-11-13 13:34:41 -080010195 /* default audio HAL major version */
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010196 uint32_t maj_version = 3;
Derek Chenf939fb72018-11-13 13:34:41 -080010197 if(property_get("vendor.audio.hal.maj.version", value, NULL))
10198 maj_version = atoi(value);
10199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010200 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -080010201 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010202 adev->device.common.module = (struct hw_module_t *)module;
10203 adev->device.common.close = adev_close;
10204
10205 adev->device.init_check = adev_init_check;
10206 adev->device.set_voice_volume = adev_set_voice_volume;
10207 adev->device.set_master_volume = adev_set_master_volume;
10208 adev->device.get_master_volume = adev_get_master_volume;
10209 adev->device.set_master_mute = adev_set_master_mute;
10210 adev->device.get_master_mute = adev_get_master_mute;
10211 adev->device.set_mode = adev_set_mode;
10212 adev->device.set_mic_mute = adev_set_mic_mute;
10213 adev->device.get_mic_mute = adev_get_mic_mute;
10214 adev->device.set_parameters = adev_set_parameters;
10215 adev->device.get_parameters = adev_get_parameters;
10216 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
10217 adev->device.open_output_stream = adev_open_output_stream;
10218 adev->device.close_output_stream = adev_close_output_stream;
10219 adev->device.open_input_stream = adev_open_input_stream;
10220 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +053010221 adev->device.create_audio_patch = adev_create_audio_patch;
10222 adev->device.release_audio_patch = adev_release_audio_patch;
10223 adev->device.get_audio_port = adev_get_audio_port;
10224 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010225 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +053010226 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010227
10228 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010229 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -080010230 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010231 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010232 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -080010233 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -070010234 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +053010235 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -070010236 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -070010237 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -070010238 /* Init audio and voice feature */
10239 audio_extn_feature_init();
10240 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -070010241 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -080010242 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -080010243 list_init(&adev->active_inputs_list);
10244 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +053010245 list_init(&adev->audio_patch_record_list);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010246 adev->io_streams_map = hashmapCreate(AUDIO_IO_PORTS_MAX, audio_extn_utils_hash_fn,
10247 audio_extn_utils_hash_eq);
10248 if (!adev->io_streams_map) {
10249 ALOGE("%s: Could not create io streams map", __func__);
10250 ret = -ENOMEM;
10251 goto adev_open_err;
10252 }
10253 adev->patch_map = hashmapCreate(AUDIO_PATCH_PORTS_MAX, audio_extn_utils_hash_fn,
10254 audio_extn_utils_hash_eq);
10255 if (!adev->patch_map) {
10256 ALOGE("%s: Could not create audio patch map", __func__);
10257 ret = -ENOMEM;
10258 goto adev_open_err;
10259 }
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -080010260 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -070010261 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +053010262 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +053010263 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010264 adev->perf_lock_opts[0] = 0x101;
10265 adev->perf_lock_opts[1] = 0x20E;
10266 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010267 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -070010268 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010269 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010270 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +053010271
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010272 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -070010273 adev->platform = platform_init(adev);
10274 if (!adev->platform) {
Eric Laurentb23d5282013-05-14 15:27:20 -070010275 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010276 ret = -EINVAL;
10277 goto adev_open_err;
Eric Laurentb23d5282013-05-14 15:27:20 -070010278 }
Eric Laurentc4aef752013-09-12 17:45:53 -070010279
Aalique Grahame22e49102018-12-18 14:23:57 -080010280 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010281 if (audio_extn_qap_is_enabled()) {
10282 ret = audio_extn_qap_init(adev);
10283 if (ret < 0) {
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010284 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010285 goto adev_open_err;
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +053010286 }
10287 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
10288 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
10289 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010290
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010291 if (audio_extn_qaf_is_enabled()) {
10292 ret = audio_extn_qaf_init(adev);
10293 if (ret < 0) {
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010294 ALOGE("%s: Failed to init platform data, aborting.", __func__);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010295 goto adev_open_err;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +053010296 }
10297
10298 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
10299 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
10300 }
10301
Derek Chenae7b0342019-02-08 15:17:04 -080010302 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -080010303 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
10304
Eric Laurentc4aef752013-09-12 17:45:53 -070010305 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
10306 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
10307 if (adev->visualizer_lib == NULL) {
10308 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
10309 } else {
10310 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
10311 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010312 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010313 "visualizer_hal_start_output");
10314 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010315 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -070010316 "visualizer_hal_stop_output");
10317 }
10318 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +053010319 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010320 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -080010321 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +080010322 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +053010323 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -070010324 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -070010325
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010326 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
10327 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
10328 if (adev->offload_effects_lib == NULL) {
10329 ALOGE("%s: DLOPEN failed for %s", __func__,
10330 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10331 } else {
10332 ALOGV("%s: DLOPEN successful for %s", __func__,
10333 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
10334 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +053010335 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010336 "offload_effects_bundle_hal_start_output");
10337 adev->offload_effects_stop_output =
10338 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
10339 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080010340 adev->offload_effects_set_hpx_state =
10341 (int (*)(bool))dlsym(adev->offload_effects_lib,
10342 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +053010343 adev->offload_effects_get_parameters =
10344 (void (*)(struct str_parms *, struct str_parms *))
10345 dlsym(adev->offload_effects_lib,
10346 "offload_effects_bundle_get_parameters");
10347 adev->offload_effects_set_parameters =
10348 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
10349 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -080010350 }
10351 }
10352
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010353 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
10354 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
10355 if (adev->adm_lib == NULL) {
10356 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
10357 } else {
10358 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
10359 adev->adm_init = (adm_init_t)
10360 dlsym(adev->adm_lib, "adm_init");
10361 adev->adm_deinit = (adm_deinit_t)
10362 dlsym(adev->adm_lib, "adm_deinit");
10363 adev->adm_register_input_stream = (adm_register_input_stream_t)
10364 dlsym(adev->adm_lib, "adm_register_input_stream");
10365 adev->adm_register_output_stream = (adm_register_output_stream_t)
10366 dlsym(adev->adm_lib, "adm_register_output_stream");
10367 adev->adm_deregister_stream = (adm_deregister_stream_t)
10368 dlsym(adev->adm_lib, "adm_deregister_stream");
10369 adev->adm_request_focus = (adm_request_focus_t)
10370 dlsym(adev->adm_lib, "adm_request_focus");
10371 adev->adm_abandon_focus = (adm_abandon_focus_t)
10372 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010373 adev->adm_set_config = (adm_set_config_t)
10374 dlsym(adev->adm_lib, "adm_set_config");
10375 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
10376 dlsym(adev->adm_lib, "adm_request_focus_v2");
10377 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
10378 dlsym(adev->adm_lib, "adm_is_noirq_avail");
10379 adev->adm_on_routing_change = (adm_on_routing_change_t)
10380 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -070010381 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
10382 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010383 }
10384 }
10385
Aalique Grahame22e49102018-12-18 14:23:57 -080010386 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010387 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +080010388 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -080010389 //initialize this to false for now,
10390 //this will be set to true through set param
10391 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -070010392
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -070010393 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010394 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -080010395
10396 if (k_enable_extended_precision)
10397 adev_verify_devices(adev);
10398
Xiaojun Sang785b5da2017-08-03 15:52:29 +080010399 adev->dsp_bit_width_enforce_mode =
10400 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010401
Dhananjay Kumard6d32152016-10-13 16:11:03 +053010402 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
10403 &adev->streams_output_cfg_list,
10404 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -070010405
Kiran Kandi910e1862013-10-29 13:29:42 -070010406 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010407
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010408 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -080010409 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
10410 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010411 trial = atoi(value);
10412 if (period_size_is_plausible_for_low_latency(trial)) {
10413 pcm_config_low_latency.period_size = trial;
10414 pcm_config_low_latency.start_threshold = trial / 4;
10415 pcm_config_low_latency.avail_min = trial / 4;
10416 configured_low_latency_capture_period_size = trial;
10417 }
10418 }
Aalique Grahame22e49102018-12-18 14:23:57 -080010419 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
10420 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -070010421 trial = atoi(value);
10422 if (period_size_is_plausible_for_low_latency(trial)) {
10423 configured_low_latency_capture_period_size = trial;
10424 }
10425 }
10426
Vignesh Kulothungan7d374312018-02-21 17:12:00 -080010427 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
10428
Eric Laurent4b084132018-10-19 17:33:43 -070010429 adev->camera_orientation = CAMERA_DEFAULT;
10430
Aalique Grahame22e49102018-12-18 14:23:57 -080010431 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
10432 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -070010433 af_period_multiplier = atoi(value);
10434 if (af_period_multiplier < 0)
10435 af_period_multiplier = 2;
10436 else if (af_period_multiplier > 4)
10437 af_period_multiplier = 4;
10438
10439 ALOGV("new period_multiplier = %d", af_period_multiplier);
10440 }
10441
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080010442 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -080010443
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -070010444 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -070010445 pthread_mutex_unlock(&adev_init_lock);
10446
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -070010447 if (adev->adm_init)
10448 adev->adm_data = adev->adm_init();
10449
Dhananjay Kumaree4d2002016-10-25 18:02:58 +053010450 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +053010451 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -080010452 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010453
10454 audio_extn_snd_mon_init();
10455 pthread_mutex_lock(&adev->lock);
10456 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
10457 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -070010458 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
10459 /*
10460 * if the battery state callback happens before charging can be queried,
10461 * it will be guarded with the adev->lock held in the cb function and so
10462 * the callback value will reflect the latest state
10463 */
10464 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010465 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +080010466 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -070010467 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +080010468 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +053010469 /* Allocate memory for Device config params */
10470 adev->device_cfg_params = (struct audio_device_config_param*)
10471 calloc(platform_get_max_codec_backend(),
10472 sizeof(struct audio_device_config_param));
10473 if (adev->device_cfg_params == NULL)
10474 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +053010475
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +053010476 /*
10477 * Check if new PSPD matrix mixer control is supported. If not
10478 * supported, then set flag so that old mixer ctrl is sent while
10479 * sending pspd coefficients on older kernel version. Query mixer
10480 * control for default pcm id and channel value one.
10481 */
10482 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
10483 "AudStr %d ChMixer Weight Ch %d", 0, 1);
10484
10485 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
10486 if (!ctl) {
10487 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
10488 __func__, mixer_ctl_name);
10489 adev->use_old_pspd_mix_ctrl = true;
10490 }
10491
Eric Laurent994a6932013-07-17 11:51:42 -070010492 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010493 return 0;
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010494
10495adev_open_err:
10496 free_map(adev->patch_map);
10497 free_map(adev->io_streams_map);
Aniket Kumar Latabc774842020-01-16 21:22:05 -080010498 free(adev->snd_dev_ref_cnt);
Aniket Kumar Lata1fda9432019-11-01 17:08:33 -070010499 pthread_mutex_destroy(&adev->lock);
10500 free(adev);
10501 adev = NULL;
10502 *device = NULL;
10503 pthread_mutex_unlock(&adev_init_lock);
10504 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010505}
10506
10507static struct hw_module_methods_t hal_module_methods = {
10508 .open = adev_open,
10509};
10510
10511struct audio_module HAL_MODULE_INFO_SYM = {
10512 .common = {
10513 .tag = HARDWARE_MODULE_TAG,
10514 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
10515 .hal_api_version = HARDWARE_HAL_API_VERSION,
10516 .id = AUDIO_HARDWARE_MODULE_ID,
10517 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -080010518 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080010519 .methods = &hal_module_methods,
10520 },
10521};