blob: 71f62a770b63a7300b5d48e1c46a534370b91576 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2019, 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
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#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
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097
Aalique Grahame22e49102018-12-18 14:23:57 -080098#define RECORD_GAIN_MIN 0.0f
99#define RECORD_GAIN_MAX 1.0f
100#define RECORD_VOLUME_CTL_MAX 0x2000
101
102/* treat as unsigned Q1.13 */
103#define APP_TYPE_GAIN_DEFAULT 0x2000
104
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700105#define PROXY_OPEN_RETRY_COUNT 100
106#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800107
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800108#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
109 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
110 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
111#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
112 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800113
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700114#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700115#define DEFAULT_VOIP_BUF_DURATION_MS 20
116#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
117#define DEFAULT_VOIP_SAMP_RATE 48000
118
119#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
120
121struct pcm_config default_pcm_config_voip_copp = {
122 .channels = 1,
123 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
124 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
125 .period_count = 2,
126 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800127 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
128 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700129};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700130
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700131#define MIN_CHANNEL_COUNT 1
132#define DEFAULT_CHANNEL_COUNT 2
133#define MAX_HIFI_CHANNEL_COUNT 8
134
Aalique Grahame22e49102018-12-18 14:23:57 -0800135#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
136#define MAX_CHANNEL_COUNT 1
137#else
138#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
139#define XSTR(x) STR(x)
140#define STR(x) #x
141#endif
142
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700143static unsigned int configured_low_latency_capture_period_size =
144 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
145
Haynes Mathew George16081042017-05-31 17:16:49 -0700146#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
147#define MMAP_PERIOD_COUNT_MIN 32
148#define MMAP_PERIOD_COUNT_MAX 512
149#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
150
Aalique Grahame22e49102018-12-18 14:23:57 -0800151/* This constant enables extended precision handling.
152 * TODO The flag is off until more testing is done.
153 */
154static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700155extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800156
Eric Laurentb23d5282013-05-14 15:27:20 -0700157struct pcm_config pcm_config_deep_buffer = {
158 .channels = 2,
159 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
160 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
161 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
162 .format = PCM_FORMAT_S16_LE,
163 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
164 .stop_threshold = INT_MAX,
165 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166};
167
168struct pcm_config pcm_config_low_latency = {
169 .channels = 2,
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
171 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
172 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
173 .format = PCM_FORMAT_S16_LE,
174 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
175 .stop_threshold = INT_MAX,
176 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177};
178
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800179struct pcm_config pcm_config_haptics_audio = {
180 .channels = 1,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
183 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
186 .stop_threshold = INT_MAX,
187 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188};
189
190struct pcm_config pcm_config_haptics = {
191 .channels = 1,
192 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
193 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
194 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
195 .format = PCM_FORMAT_S16_LE,
196 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
197 .stop_threshold = INT_MAX,
198 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
199};
200
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700201static int af_period_multiplier = 4;
202struct pcm_config pcm_config_rt = {
203 .channels = 2,
204 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
205 .period_size = ULL_PERIOD_SIZE, //1 ms
206 .period_count = 512, //=> buffer size is 512ms
207 .format = PCM_FORMAT_S16_LE,
208 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
209 .stop_threshold = INT_MAX,
210 .silence_threshold = 0,
211 .silence_size = 0,
212 .avail_min = ULL_PERIOD_SIZE, //1 ms
213};
214
Eric Laurentb23d5282013-05-14 15:27:20 -0700215struct pcm_config pcm_config_hdmi_multi = {
216 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
217 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
218 .period_size = HDMI_MULTI_PERIOD_SIZE,
219 .period_count = HDMI_MULTI_PERIOD_COUNT,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = 0,
222 .stop_threshold = INT_MAX,
223 .avail_min = 0,
224};
225
Haynes Mathew George16081042017-05-31 17:16:49 -0700226struct pcm_config pcm_config_mmap_playback = {
227 .channels = 2,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = MMAP_PERIOD_SIZE*8,
233 .stop_threshold = INT32_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700239struct pcm_config pcm_config_hifi = {
240 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
241 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
242 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
243 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
244 .format = PCM_FORMAT_S24_3LE,
245 .start_threshold = 0,
246 .stop_threshold = INT_MAX,
247 .avail_min = 0,
248};
249
Eric Laurentb23d5282013-05-14 15:27:20 -0700250struct pcm_config pcm_config_audio_capture = {
251 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700252 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
253 .format = PCM_FORMAT_S16_LE,
254};
255
Haynes Mathew George16081042017-05-31 17:16:49 -0700256struct pcm_config pcm_config_mmap_capture = {
257 .channels = 2,
258 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
259 .period_size = MMAP_PERIOD_SIZE,
260 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
261 .format = PCM_FORMAT_S16_LE,
262 .start_threshold = 0,
263 .stop_threshold = INT_MAX,
264 .silence_threshold = 0,
265 .silence_size = 0,
266 .avail_min = MMAP_PERIOD_SIZE, //1 ms
267};
268
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700269#define AFE_PROXY_CHANNEL_COUNT 2
270#define AFE_PROXY_SAMPLING_RATE 48000
271
272#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
273#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
274
275struct pcm_config pcm_config_afe_proxy_playback = {
276 .channels = AFE_PROXY_CHANNEL_COUNT,
277 .rate = AFE_PROXY_SAMPLING_RATE,
278 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
279 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
280 .format = PCM_FORMAT_S16_LE,
281 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
282 .stop_threshold = INT_MAX,
283 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284};
285
286#define AFE_PROXY_RECORD_PERIOD_SIZE 768
287#define AFE_PROXY_RECORD_PERIOD_COUNT 4
288
Aalique Grahame22e49102018-12-18 14:23:57 -0800289struct pcm_config pcm_config_audio_capture_rt = {
290 .channels = 2,
291 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
292 .period_size = ULL_PERIOD_SIZE,
293 .period_count = 512,
294 .format = PCM_FORMAT_S16_LE,
295 .start_threshold = 0,
296 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
297 .silence_threshold = 0,
298 .silence_size = 0,
299 .avail_min = ULL_PERIOD_SIZE, //1 ms
300};
301
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700302struct pcm_config pcm_config_afe_proxy_record = {
303 .channels = AFE_PROXY_CHANNEL_COUNT,
304 .rate = AFE_PROXY_SAMPLING_RATE,
305 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
306 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
307 .format = PCM_FORMAT_S16_LE,
308 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
309 .stop_threshold = INT_MAX,
310 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
311};
312
Ashish Jainf1eaa582016-05-23 20:54:24 +0530313#define AUDIO_MAX_PCM_FORMATS 7
314
315const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
316 [AUDIO_FORMAT_DEFAULT] = 0,
317 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
318 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
319 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
320 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
321 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
322 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
323};
324
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800325const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700326 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
327 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800328 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700329 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
330 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700331 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700332 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700333 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
334 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700341 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
342 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700343 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800344 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700345
Eric Laurentb23d5282013-05-14 15:27:20 -0700346 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700347 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530348 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
349 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
350 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530351 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
352 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700353 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700354 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700355 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700356 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700357
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800358 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800359 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700360 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700361
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700362 [USECASE_VOICE2_CALL] = "voice2-call",
363 [USECASE_VOLTE_CALL] = "volte-call",
364 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800365 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800366 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
367 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800368 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700369 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
370 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
371 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800372 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
373 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
374 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
375
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700376 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
377 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700378 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
379 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700380
381 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
382 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530383 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700384
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530385 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530386 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
387 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700388
389 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
390 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530391 /* For Interactive Audio Streams */
392 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700400
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800401 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
402
Derek Chenf6318be2017-06-12 17:16:24 -0400403 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
404
405 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
406 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
407 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
408 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700409};
410
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700411static const audio_usecase_t offload_usecases[] = {
412 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700413 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
414 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
415 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
416 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
417 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
418 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
419 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700421};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800422
Varun Balaraje49253e2017-07-06 19:48:56 +0530423static const audio_usecase_t interactive_usecases[] = {
424 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
426 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
427 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
428 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
429 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
432};
433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800434#define STRING_TO_ENUM(string) { #string, string }
435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436struct string_to_enum {
437 const char *name;
438 uint32_t value;
439};
440
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700441static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800442 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
444 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
445 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700446 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800447 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700450 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
451 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
452 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
453 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
455 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
456 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
457 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
458 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800461};
462
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700463static const struct string_to_enum formats_name_to_enum_table[] = {
464 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
465 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
466 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700467 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
468 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
469 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700470 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800471 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
472 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700473 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800474};
475
476//list of all supported sample rates by HDMI specification.
477static const int out_hdmi_sample_rates[] = {
478 32000, 44100, 48000, 88200, 96000, 176400, 192000,
479};
480
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700481static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800482 STRING_TO_ENUM(32000),
483 STRING_TO_ENUM(44100),
484 STRING_TO_ENUM(48000),
485 STRING_TO_ENUM(88200),
486 STRING_TO_ENUM(96000),
487 STRING_TO_ENUM(176400),
488 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700489};
490
Carter Hsu2e429db2019-05-14 18:50:52 +0800491struct in_effect_list {
492 struct listnode list;
493 effect_handle_t handle;
494};
495
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700496static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700497static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700498static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700499//cache last MBDRC cal step level
500static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700501
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530502static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
503static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700504static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800505static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530506static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530507
Vatsal Buchac09ae062018-11-14 13:25:08 +0530508#ifdef AUDIO_FEATURE_ENABLED_GCOV
509extern void __gcov_flush();
510static void enable_gcov()
511{
512 __gcov_flush();
513}
514#else
515static void enable_gcov()
516{
517}
518#endif
519
justinweng20fb6d82019-02-21 18:49:00 -0700520static int in_set_microphone_direction(const struct audio_stream_in *stream,
521 audio_microphone_direction_t dir);
522static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
523
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700524static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
525 int flags __unused)
526{
527 int dir = 0;
528 switch (uc_id) {
529 case USECASE_AUDIO_RECORD_LOW_LATENCY:
530 dir = 1;
531 case USECASE_AUDIO_PLAYBACK_ULL:
532 break;
533 default:
534 return false;
535 }
536
537 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
538 PCM_PLAYBACK : PCM_CAPTURE);
539 if (adev->adm_is_noirq_avail)
540 return adev->adm_is_noirq_avail(adev->adm_data,
541 adev->snd_card, dev_id, dir);
542 return false;
543}
544
545static void register_out_stream(struct stream_out *out)
546{
547 struct audio_device *adev = out->dev;
548 if (is_offload_usecase(out->usecase) ||
549 !adev->adm_register_output_stream)
550 return;
551
552 // register stream first for backward compatibility
553 adev->adm_register_output_stream(adev->adm_data,
554 out->handle,
555 out->flags);
556
557 if (!adev->adm_set_config)
558 return;
559
560 if (out->realtime)
561 adev->adm_set_config(adev->adm_data,
562 out->handle,
563 out->pcm, &out->config);
564}
565
566static void register_in_stream(struct stream_in *in)
567{
568 struct audio_device *adev = in->dev;
569 if (!adev->adm_register_input_stream)
570 return;
571
572 adev->adm_register_input_stream(adev->adm_data,
573 in->capture_handle,
574 in->flags);
575
576 if (!adev->adm_set_config)
577 return;
578
579 if (in->realtime)
580 adev->adm_set_config(adev->adm_data,
581 in->capture_handle,
582 in->pcm,
583 &in->config);
584}
585
586static void request_out_focus(struct stream_out *out, long ns)
587{
588 struct audio_device *adev = out->dev;
589
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700590 if (adev->adm_request_focus_v2)
591 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
592 else if (adev->adm_request_focus)
593 adev->adm_request_focus(adev->adm_data, out->handle);
594}
595
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700596static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700597{
598 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700599 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700600
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700601 if (adev->adm_request_focus_v2_1)
602 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
603 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700604 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
605 else if (adev->adm_request_focus)
606 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700607
608 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700609}
610
611static void release_out_focus(struct stream_out *out)
612{
613 struct audio_device *adev = out->dev;
614
615 if (adev->adm_abandon_focus)
616 adev->adm_abandon_focus(adev->adm_data, out->handle);
617}
618
619static void release_in_focus(struct stream_in *in)
620{
621 struct audio_device *adev = in->dev;
622 if (adev->adm_abandon_focus)
623 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
624}
625
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530626static int parse_snd_card_status(struct str_parms *parms, int *card,
627 card_status_t *status)
628{
629 char value[32]={0};
630 char state[32]={0};
631
632 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
633 if (ret < 0)
634 return -1;
635
636 // sscanf should be okay as value is of max length 32.
637 // same as sizeof state.
638 if (sscanf(value, "%d,%s", card, state) < 2)
639 return -1;
640
641 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
642 CARD_STATUS_OFFLINE;
643 return 0;
644}
645
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700646static inline void adjust_frames_for_device_delay(struct stream_out *out,
647 uint32_t *dsp_frames) {
648 // Adjustment accounts for A2dp encoder latency with offload usecases
649 // Note: Encoder latency is returned in ms.
650 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
651 unsigned long offset =
652 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
653 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
654 }
655}
656
vivek mehtaa76401a2015-04-24 14:12:15 -0700657__attribute__ ((visibility ("default")))
658bool audio_hw_send_gain_dep_calibration(int level) {
659 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700660 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700661
662 pthread_mutex_lock(&adev_init_lock);
663
664 if (adev != NULL && adev->platform != NULL) {
665 pthread_mutex_lock(&adev->lock);
666 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700667
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530668 // cache level info for any of the use case which
669 // was not started.
670 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700671
vivek mehtaa76401a2015-04-24 14:12:15 -0700672 pthread_mutex_unlock(&adev->lock);
673 } else {
674 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
675 }
676
677 pthread_mutex_unlock(&adev_init_lock);
678
679 return ret_val;
680}
681
Ashish Jain5106d362016-05-11 19:23:33 +0530682static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
683{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800684 bool gapless_enabled = false;
685 const char *mixer_ctl_name = "Compress Gapless Playback";
686 struct mixer_ctl *ctl;
687
688 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700689 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530690
691 /*Disable gapless if its AV playback*/
692 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800693
694 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
695 if (!ctl) {
696 ALOGE("%s: Could not get ctl for mixer cmd - %s",
697 __func__, mixer_ctl_name);
698 return -EINVAL;
699 }
700
701 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
702 ALOGE("%s: Could not set gapless mode %d",
703 __func__, gapless_enabled);
704 return -EINVAL;
705 }
706 return 0;
707}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700708
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700709__attribute__ ((visibility ("default")))
710int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
711 int table_size) {
712 int ret_val = 0;
713 ALOGV("%s: enter ... ", __func__);
714
715 pthread_mutex_lock(&adev_init_lock);
716 if (adev == NULL) {
717 ALOGW("%s: adev is NULL .... ", __func__);
718 goto done;
719 }
720
721 pthread_mutex_lock(&adev->lock);
722 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
723 pthread_mutex_unlock(&adev->lock);
724done:
725 pthread_mutex_unlock(&adev_init_lock);
726 ALOGV("%s: exit ... ", __func__);
727 return ret_val;
728}
729
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800730bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800731{
732 bool ret = false;
733 ALOGV("%s: enter ...", __func__);
734
735 pthread_mutex_lock(&adev_init_lock);
736
737 if (adev != NULL && adev->platform != NULL) {
738 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800739 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800740 pthread_mutex_unlock(&adev->lock);
741 }
742
743 pthread_mutex_unlock(&adev_init_lock);
744
745 ALOGV("%s: exit with ret %d", __func__, ret);
746 return ret;
747}
Aalique Grahame22e49102018-12-18 14:23:57 -0800748
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700749static bool is_supported_format(audio_format_t format)
750{
Eric Laurent86e17132013-09-12 17:49:30 -0700751 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530752 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530753 format == AUDIO_FORMAT_AAC_LC ||
754 format == AUDIO_FORMAT_AAC_HE_V1 ||
755 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530756 format == AUDIO_FORMAT_AAC_ADTS_LC ||
757 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
758 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530759 format == AUDIO_FORMAT_AAC_LATM_LC ||
760 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
761 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530762 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
763 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530764 format == AUDIO_FORMAT_PCM_FLOAT ||
765 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700766 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530767 format == AUDIO_FORMAT_AC3 ||
768 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700769 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530770 format == AUDIO_FORMAT_DTS ||
771 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800772 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530773 format == AUDIO_FORMAT_ALAC ||
774 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530775 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530776 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800777 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530778 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700779 format == AUDIO_FORMAT_APTX ||
780 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800781 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700782
783 return false;
784}
785
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700786static inline bool is_mmap_usecase(audio_usecase_t uc_id)
787{
788 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
789 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
790}
791
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700792static inline bool is_valid_volume(float left, float right)
793{
794 return ((left >= 0.0f && right >= 0.0f) ? true : false);
795}
796
Avinash Vaish71a8b972014-07-24 15:36:33 +0530797static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
798 struct audio_usecase *uc_info)
799{
800 struct listnode *node;
801 struct audio_usecase *usecase;
802
803 if (uc_info == NULL)
804 return -EINVAL;
805
806 /* Re-route all voice usecases on the shared backend other than the
807 specified usecase to new snd devices */
808 list_for_each(node, &adev->usecase_list) {
809 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800810 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530811 enable_audio_route(adev, usecase);
812 }
813 return 0;
814}
815
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530816static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530817{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530818 ALOGV("%s", __func__);
819 audio_route_apply_and_update_path(adev->audio_route,
820 "asrc-mode");
821 adev->asrc_mode_enabled = true;
822}
823
824static void disable_asrc_mode(struct audio_device *adev)
825{
826 ALOGV("%s", __func__);
827 audio_route_reset_and_update_path(adev->audio_route,
828 "asrc-mode");
829 adev->asrc_mode_enabled = false;
830}
831
832/*
833 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
834 * 44.1 or Native DSD backends are enabled for any of current use case.
835 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
836 * - Disable current mix path use case(Headphone backend) and re-enable it with
837 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
838 * e.g. Naitve DSD or Headphone 44.1 -> + 48
839 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530840static void check_and_set_asrc_mode(struct audio_device *adev,
841 struct audio_usecase *uc_info,
842 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530843{
844 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530845 int i, num_new_devices = 0;
846 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
847 /*
848 *Split snd device for new combo use case
849 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
850 */
851 if (platform_split_snd_device(adev->platform,
852 snd_device,
853 &num_new_devices,
854 split_new_snd_devices) == 0) {
855 for (i = 0; i < num_new_devices; i++)
856 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
857 } else {
858 int new_backend_idx = platform_get_backend_index(snd_device);
859 if (((new_backend_idx == HEADPHONE_BACKEND) ||
860 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
861 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
862 !adev->asrc_mode_enabled) {
863 struct listnode *node = NULL;
864 struct audio_usecase *uc = NULL;
865 struct stream_out *curr_out = NULL;
866 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
867 int i, num_devices, ret = 0;
868 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530869
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530870 list_for_each(node, &adev->usecase_list) {
871 uc = node_to_item(node, struct audio_usecase, list);
872 curr_out = (struct stream_out*) uc->stream.out;
873 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
874 /*
875 *Split snd device for existing combo use case
876 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
877 */
878 ret = platform_split_snd_device(adev->platform,
879 uc->out_snd_device,
880 &num_devices,
881 split_snd_devices);
882 if (ret < 0 || num_devices == 0) {
883 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
884 split_snd_devices[0] = uc->out_snd_device;
885 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800886 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530887 for (i = 0; i < num_devices; i++) {
888 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
889 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
890 if((new_backend_idx == HEADPHONE_BACKEND) &&
891 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
892 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
893 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
894 __func__);
895 enable_asrc_mode(adev);
896 break;
897 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
898 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
899 (usecase_backend_idx == HEADPHONE_BACKEND)) {
900 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
901 __func__);
902 disable_audio_route(adev, uc);
903 disable_snd_device(adev, uc->out_snd_device);
904 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
905 if (new_backend_idx == DSD_NATIVE_BACKEND)
906 audio_route_apply_and_update_path(adev->audio_route,
907 "hph-true-highquality-mode");
908 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
909 (curr_out->bit_width >= 24))
910 audio_route_apply_and_update_path(adev->audio_route,
911 "hph-highquality-mode");
912 enable_asrc_mode(adev);
913 enable_snd_device(adev, uc->out_snd_device);
914 enable_audio_route(adev, uc);
915 break;
916 }
917 }
918 // reset split devices count
919 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800920 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530921 if (adev->asrc_mode_enabled)
922 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530923 }
924 }
925 }
926}
927
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700928static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
929 struct audio_effect_config effect_config,
930 unsigned int param_value)
931{
932 char mixer_ctl_name[] = "Audio Effect";
933 struct mixer_ctl *ctl;
934 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800935 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700936
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700937 if (in == NULL) {
938 ALOGE("%s: active input stream is NULL", __func__);
939 return -EINVAL;
940 }
941
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700942 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
943 if (!ctl) {
944 ALOGE("%s: Could not get mixer ctl - %s",
945 __func__, mixer_ctl_name);
946 return -EINVAL;
947 }
948
949 set_values[0] = 1; //0:Rx 1:Tx
950 set_values[1] = in->app_type_cfg.app_type;
951 set_values[2] = (long)effect_config.module_id;
952 set_values[3] = (long)effect_config.instance_id;
953 set_values[4] = (long)effect_config.param_id;
954 set_values[5] = param_value;
955
956 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
957
958 return 0;
959
960}
961
962static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
963 int effect_type, unsigned int *param_value)
964{
965 int ret = 0;
966 struct audio_effect_config other_effect_config;
967 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800968 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700969
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700970 if (in == NULL) {
971 ALOGE("%s: active input stream is NULL", __func__);
972 return -EINVAL;
973 }
974
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700975 usecase = get_usecase_from_list(adev, in->usecase);
976 if (!usecase)
977 return -EINVAL;
978
979 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
980 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
981 if (ret < 0) {
982 ALOGE("%s Failed to get effect params %d", __func__, ret);
983 return ret;
984 }
985
986 if (module_id == other_effect_config.module_id) {
987 //Same module id for AEC/NS. Values need to be combined
988 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
989 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
990 *param_value |= other_effect_config.param_value;
991 }
992 }
993
994 return ret;
995}
996
997static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +0530998{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700999 struct audio_effect_config effect_config;
1000 struct audio_usecase *usecase = NULL;
1001 int ret = 0;
1002 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001003 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001004
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001005 if(!voice_extn_is_dynamic_ecns_enabled())
1006 return ENOSYS;
1007
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001008 if (!in) {
1009 ALOGE("%s: Invalid input stream", __func__);
1010 return -EINVAL;
1011 }
1012
1013 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1014
1015 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001016 if (usecase == NULL) {
1017 ALOGE("%s: Could not find the usecase (%d) in the list",
1018 __func__, in->usecase);
1019 return -EINVAL;
1020 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001021
1022 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1023 if (ret < 0) {
1024 ALOGE("%s Failed to get module id %d", __func__, ret);
1025 return ret;
1026 }
1027 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1028 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1029
1030 if(enable)
1031 param_value = effect_config.param_value;
1032
1033 /*Special handling for AEC & NS effects Param values need to be
1034 updated if module ids are same*/
1035
1036 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1037 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1038 if (ret < 0)
1039 return ret;
1040 }
1041
1042 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1043
1044 return ret;
1045}
1046
1047static void check_and_enable_effect(struct audio_device *adev)
1048{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001049 if(!voice_extn_is_dynamic_ecns_enabled())
1050 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001051
Eric Laurent637e2d42018-11-15 12:24:31 -08001052 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001053
Eric Laurent637e2d42018-11-15 12:24:31 -08001054 if (in != NULL && !in->standby) {
1055 if (in->enable_aec)
1056 enable_disable_effect(adev, EFFECT_AEC, true);
1057
1058 if (in->enable_ns &&
1059 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1060 enable_disable_effect(adev, EFFECT_NS, true);
1061 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001062 }
1063}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001064
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001065int pcm_ioctl(struct pcm *pcm, int request, ...)
1066{
1067 va_list ap;
1068 void * arg;
1069 int pcm_fd = *(int*)pcm;
1070
1071 va_start(ap, request);
1072 arg = va_arg(ap, void *);
1073 va_end(ap);
1074
1075 return ioctl(pcm_fd, request, arg);
1076}
1077
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001078int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001079 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001080{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001081 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001082 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301083 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301084 struct stream_in *in = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301085 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001086
1087 if (usecase == NULL)
1088 return -EINVAL;
1089
1090 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1091
Carter Hsu2e429db2019-05-14 18:50:52 +08001092 if (usecase->type == PCM_CAPTURE) {
1093 struct stream_in *in = usecase->stream.in;
1094 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001095 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001096
1097 if (in) {
1098 if (in->enable_aec || in->enable_ec_port) {
1099 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
1100 struct listnode *node;
1101 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1102 USECASE_AUDIO_PLAYBACK_VOIP);
1103 if (voip_usecase) {
1104 out_device = voip_usecase->stream.out->devices;
1105 } else if (adev->primary_output &&
1106 !adev->primary_output->standby) {
1107 out_device = adev->primary_output->devices;
1108 } else {
1109 list_for_each(node, &adev->usecase_list) {
1110 uinfo = node_to_item(node, struct audio_usecase, list);
1111 if (uinfo->type != PCM_CAPTURE) {
1112 out_device = uinfo->stream.out->devices;
1113 break;
1114 }
1115 }
1116 }
1117 platform_set_echo_reference(adev, true, out_device);
1118 in->ec_opened = true;
1119 }
1120 }
1121 } else if (usecase->type == TRANSCODE_LOOPBACK_TX) {
1122 snd_device = usecase->in_snd_device;
1123 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001124 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001125 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001126
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001127#ifdef DS1_DOLBY_DAP_ENABLED
1128 audio_extn_dolby_set_dmid(adev);
1129 audio_extn_dolby_set_endpoint(adev);
1130#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001131 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001132 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301133 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001134 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001135 if (audio_extn_is_maxx_audio_enabled())
1136 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301137 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301138 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1139 out = usecase->stream.out;
1140 if (out && out->compr)
1141 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1142 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301143
1144 if (usecase->type == PCM_CAPTURE) {
1145 in = usecase->stream.in;
1146 if (in && is_loopback_input_device(in->device)) {
1147 ALOGD("%s: set custom mtmx params v1", __func__);
1148 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1149 }
1150 } else {
1151 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1152 }
Manish Dewangan58229382017-02-02 15:48:41 +05301153
Andy Hung756ecc12018-10-19 17:47:12 -07001154 // we shouldn't truncate mixer_path
1155 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1156 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1157 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001158 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001159 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301160 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1161 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1162 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1163 if (parms) {
1164 audio_extn_fm_set_parameters(adev, parms);
1165 str_parms_destroy(parms);
1166 }
1167 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001168 ALOGV("%s: exit", __func__);
1169 return 0;
1170}
1171
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001172int disable_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];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301177 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001178
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301179 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001180 return -EINVAL;
1181
1182 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301183 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 snd_device = usecase->in_snd_device;
1185 else
1186 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001187 // we shouldn't truncate mixer_path
1188 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1189 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1190 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001191 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001192 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001193 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001194 if (usecase->type == PCM_CAPTURE) {
1195 struct stream_in *in = usecase->stream.in;
1196 if (in && in->ec_opened) {
1197 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
1198 in->ec_opened = false;
1199 }
1200 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001201 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301202 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301203
1204 if (usecase->type == PCM_CAPTURE) {
1205 in = usecase->stream.in;
1206 if (in && is_loopback_input_device(in->device)) {
1207 ALOGD("%s: reset custom mtmx params v1", __func__);
1208 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1209 }
1210 } else {
1211 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1212 }
1213
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001214 if ((usecase->type == PCM_PLAYBACK) &&
1215 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301216 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301217
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001218 ALOGV("%s: exit", __func__);
1219 return 0;
1220}
1221
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001222int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001223 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301225 int i, num_devices = 0;
1226 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001227 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1228
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001229 if (snd_device < SND_DEVICE_MIN ||
1230 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001231 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001232 return -EINVAL;
1233 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001234
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001235 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001236 ALOGE("%s: Invalid sound device returned", __func__);
1237 return -EINVAL;
1238 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001239
1240 adev->snd_dev_ref_cnt[snd_device]++;
1241
1242 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1243 (platform_split_snd_device(adev->platform,
1244 snd_device,
1245 &num_devices,
1246 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001247 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001248 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001249 return 0;
1250 }
1251
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001252 if (audio_extn_spkr_prot_is_enabled())
1253 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001254
Aalique Grahame22e49102018-12-18 14:23:57 -08001255 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1256
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001257 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1258 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001259 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1260 goto err;
1261 }
1262 audio_extn_dev_arbi_acquire(snd_device);
1263 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001264 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001265 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001266 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001267 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001268 } else if (platform_split_snd_device(adev->platform,
1269 snd_device,
1270 &num_devices,
1271 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301272 for (i = 0; i < num_devices; i++) {
1273 enable_snd_device(adev, new_snd_devices[i]);
1274 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001275 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001276 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001277 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301278
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301279
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001280 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1281 (audio_extn_a2dp_start_playback() < 0)) {
1282 ALOGE(" fail to configure A2dp Source control path ");
1283 goto err;
1284 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001285
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001286 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1287 (audio_extn_a2dp_start_capture() < 0)) {
1288 ALOGE(" fail to configure A2dp Sink control path ");
1289 goto err;
1290 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301291
Zhou Song12c29502019-03-16 10:37:18 +08001292 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1293 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1294 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1295 (audio_extn_sco_start_configuration() < 0)) {
1296 ALOGE(" fail to configure sco control path ");
1297 goto err;
1298 }
1299
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001300 /* due to the possibility of calibration overwrite between listen
1301 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001302 audio_extn_sound_trigger_update_device_status(snd_device,
1303 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301304 audio_extn_listen_update_device_status(snd_device,
1305 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001306 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001307 audio_extn_sound_trigger_update_device_status(snd_device,
1308 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301309 audio_extn_listen_update_device_status(snd_device,
1310 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001311 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001312 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001313 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001314 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301315
1316 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1317 !adev->native_playback_enabled &&
1318 audio_is_true_native_stream_active(adev)) {
1319 ALOGD("%s: %d: napb: enabling native mode in hardware",
1320 __func__, __LINE__);
1321 audio_route_apply_and_update_path(adev->audio_route,
1322 "true-native-mode");
1323 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301324 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301325 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1326 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001327 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001328 ALOGD("%s: init ec ref loopback", __func__);
1329 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1330 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001331 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001332 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001333err:
1334 adev->snd_dev_ref_cnt[snd_device]--;
1335 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001336}
1337
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001338int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001339 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301341 int i, num_devices = 0;
1342 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001343 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1344
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001345 if (snd_device < SND_DEVICE_MIN ||
1346 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001347 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001348 return -EINVAL;
1349 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001350
1351 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1352 ALOGE("%s: Invalid sound device returned", __func__);
1353 return -EINVAL;
1354 }
1355
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001356 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1357 ALOGE("%s: device ref cnt is already 0", __func__);
1358 return -EINVAL;
1359 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001360
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001361 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001362
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001363
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001364 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001365 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301366
Aalique Grahame22e49102018-12-18 14:23:57 -08001367 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1368
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001369 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1370 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001371 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001372
1373 // when speaker device is disabled, reset swap.
1374 // will be renabled on usecase start
1375 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001376 } else if (platform_split_snd_device(adev->platform,
1377 snd_device,
1378 &num_devices,
1379 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301380 for (i = 0; i < num_devices; i++) {
1381 disable_snd_device(adev, new_snd_devices[i]);
1382 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001383 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001384 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001385 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001386 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001387
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001388 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301389 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001390 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001391 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001392 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001393 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301394 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001395 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301396 adev->native_playback_enabled) {
1397 ALOGD("%s: %d: napb: disabling native mode in hardware",
1398 __func__, __LINE__);
1399 audio_route_reset_and_update_path(adev->audio_route,
1400 "true-native-mode");
1401 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001402 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301403 adev->asrc_mode_enabled) {
1404 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301405 disable_asrc_mode(adev);
1406 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001407 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301408 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001409 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001410 ALOGD("%s: deinit ec ref loopback", __func__);
1411 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1412 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001413
1414 audio_extn_utils_release_snd_device(snd_device);
1415 } else {
1416 if (platform_split_snd_device(adev->platform,
1417 snd_device,
1418 &num_devices,
1419 new_snd_devices) == 0) {
1420 for (i = 0; i < num_devices; i++) {
1421 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1422 }
1423 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001424 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001425
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001426 return 0;
1427}
1428
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001429/*
1430 legend:
1431 uc - existing usecase
1432 new_uc - new usecase
1433 d1, d11, d2 - SND_DEVICE enums
1434 a1, a2 - corresponding ANDROID device enums
1435 B1, B2 - backend strings
1436
1437case 1
1438 uc->dev d1 (a1) B1
1439 new_uc->dev d1 (a1), d2 (a2) B1, B2
1440
1441 resolution: disable and enable uc->dev on d1
1442
1443case 2
1444 uc->dev d1 (a1) B1
1445 new_uc->dev d11 (a1) B1
1446
1447 resolution: need to switch uc since d1 and d11 are related
1448 (e.g. speaker and voice-speaker)
1449 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1450
1451case 3
1452 uc->dev d1 (a1) B1
1453 new_uc->dev d2 (a2) B2
1454
1455 resolution: no need to switch uc
1456
1457case 4
1458 uc->dev d1 (a1) B1
1459 new_uc->dev d2 (a2) B1
1460
1461 resolution: disable enable uc-dev on d2 since backends match
1462 we cannot enable two streams on two different devices if they
1463 share the same backend. e.g. if offload is on speaker device using
1464 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1465 using the same backend, offload must also be switched to voice-handset.
1466
1467case 5
1468 uc->dev d1 (a1) B1
1469 new_uc->dev d1 (a1), d2 (a2) B1
1470
1471 resolution: disable enable uc-dev on d2 since backends match
1472 we cannot enable two streams on two different devices if they
1473 share the same backend.
1474
1475case 6
1476 uc->dev d1 (a1) B1
1477 new_uc->dev d2 (a1) B2
1478
1479 resolution: no need to switch
1480
1481case 7
1482 uc->dev d1 (a1), d2 (a2) B1, B2
1483 new_uc->dev d1 (a1) B1
1484
1485 resolution: no need to switch
1486
Zhou Song4ba65882018-07-09 14:48:07 +08001487case 8
1488 uc->dev d1 (a1) B1
1489 new_uc->dev d11 (a1), d2 (a2) B1, B2
1490 resolution: compared to case 1, for this case, d1 and d11 are related
1491 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001492*/
1493static snd_device_t derive_playback_snd_device(void * platform,
1494 struct audio_usecase *uc,
1495 struct audio_usecase *new_uc,
1496 snd_device_t new_snd_device)
1497{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301498 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001499
1500 snd_device_t d1 = uc->out_snd_device;
1501 snd_device_t d2 = new_snd_device;
1502
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301503 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301504 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301505 a1 = uc->stream.inout->out_config.devices;
1506 a2 = new_uc->stream.inout->out_config.devices;
1507 break;
1508 default :
1509 a1 = uc->stream.out->devices;
1510 a2 = new_uc->stream.out->devices;
1511 break;
1512 }
1513
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001514 // Treat as a special case when a1 and a2 are not disjoint
1515 if ((a1 != a2) && (a1 & a2)) {
1516 snd_device_t d3[2];
1517 int num_devices = 0;
1518 int ret = platform_split_snd_device(platform,
1519 popcount(a1) > 1 ? d1 : d2,
1520 &num_devices,
1521 d3);
1522 if (ret < 0) {
1523 if (ret != -ENOSYS) {
1524 ALOGW("%s failed to split snd_device %d",
1525 __func__,
1526 popcount(a1) > 1 ? d1 : d2);
1527 }
1528 goto end;
1529 }
1530
1531 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1532 // But if it does happen, we need to give priority to d2 if
1533 // the combo devices active on the existing usecase share a backend.
1534 // This is because we cannot have a usecase active on a combo device
1535 // and a new usecase requests one device in this combo pair.
1536 if (platform_check_backends_match(d3[0], d3[1])) {
1537 return d2; // case 5
1538 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001539 // check if d1 is related to any of d3's
1540 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001541 return d1; // case 1
1542 else
1543 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001544 }
1545 } else {
1546 if (platform_check_backends_match(d1, d2)) {
1547 return d2; // case 2, 4
1548 } else {
1549 return d1; // case 6, 3
1550 }
1551 }
1552
1553end:
1554 return d2; // return whatever was calculated before.
1555}
1556
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001557static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301558 struct audio_usecase *uc_info,
1559 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001560{
1561 struct listnode *node;
1562 struct audio_usecase *usecase;
1563 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301564 snd_device_t uc_derive_snd_device;
1565 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001566 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1567 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001568 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301569 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001570 /*
1571 * This function is to make sure that all the usecases that are active on
1572 * the hardware codec backend are always routed to any one device that is
1573 * handled by the hardware codec.
1574 * For example, if low-latency and deep-buffer usecases are currently active
1575 * on speaker and out_set_parameters(headset) is received on low-latency
1576 * output, then we have to make sure deep-buffer is also switched to headset,
1577 * because of the limitation that both the devices cannot be enabled
1578 * at the same time as they share the same backend.
1579 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001580 /*
1581 * This call is to check if we need to force routing for a particular stream
1582 * If there is a backend configuration change for the device when a
1583 * new stream starts, then ADM needs to be closed and re-opened with the new
1584 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001585 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001586 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001587 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1588 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301589 /* For a2dp device reconfigure all active sessions
1590 * with new AFE encoder format based on a2dp state
1591 */
1592 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1593 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1594 audio_extn_a2dp_is_force_device_switch()) {
1595 force_routing = true;
1596 force_restart_session = true;
1597 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301598 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1599
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001600 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001601 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001602 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1604 switch_device[i] = false;
1605
1606 list_for_each(node, &adev->usecase_list) {
1607 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001608
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301609 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1610 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301611 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301612 platform_get_snd_device_name(usecase->out_snd_device),
1613 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301614 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1615 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1616 usecase, uc_info, snd_device);
1617 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1618 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1619 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1620 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001621 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301622 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1623 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1624 ((force_restart_session) ||
1625 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301626 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1627 __func__, use_case_table[usecase->id],
1628 platform_get_snd_device_name(usecase->out_snd_device));
1629 disable_audio_route(adev, usecase);
1630 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301631 /* Enable existing usecase on derived playback device */
1632 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301633 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301634 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001635 }
1636 }
1637
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301638 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1639 num_uc_to_switch);
1640
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001641 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001642 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001643
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301644 /* Make sure the previous devices to be disabled first and then enable the
1645 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001646 list_for_each(node, &adev->usecase_list) {
1647 usecase = node_to_item(node, struct audio_usecase, list);
1648 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001649 /* Check if output sound device to be switched can be split and if any
1650 of the split devices match with derived sound device */
1651 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1652 &num_devices, split_snd_devices) == 0) {
1653 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1654 for (i = 0; i < num_devices; i++) {
1655 /* Disable devices that do not match with derived sound device */
1656 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1657 disable_snd_device(adev, split_snd_devices[i]);
1658 }
1659 } else {
1660 disable_snd_device(adev, usecase->out_snd_device);
1661 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001662 }
1663 }
1664
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001665 list_for_each(node, &adev->usecase_list) {
1666 usecase = node_to_item(node, struct audio_usecase, list);
1667 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001668 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1669 &num_devices, split_snd_devices) == 0) {
1670 /* Enable derived sound device only if it does not match with
1671 one of the split sound devices. This is because the matching
1672 sound device was not disabled */
1673 bool should_enable = true;
1674 for (i = 0; i < num_devices; i++) {
1675 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1676 should_enable = false;
1677 break;
1678 }
1679 }
1680 if (should_enable)
1681 enable_snd_device(adev, derive_snd_device[usecase->id]);
1682 } else {
1683 enable_snd_device(adev, derive_snd_device[usecase->id]);
1684 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001685 }
1686 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001687
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001688 /* Re-route all the usecases on the shared backend other than the
1689 specified usecase to new snd devices */
1690 list_for_each(node, &adev->usecase_list) {
1691 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301692 /* Update the out_snd_device only before enabling the audio route */
1693 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301694 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301695 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301696 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301697 use_case_table[usecase->id],
1698 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001699 /* Update voc calibration before enabling VoIP route */
1700 if (usecase->type == VOIP_CALL)
1701 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001702 usecase->out_snd_device,
1703 platform_get_input_snd_device(
1704 adev->platform, NULL,
1705 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301706 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301707 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001708 out_set_voip_volume(&usecase->stream.out->stream,
1709 usecase->stream.out->volume_l,
1710 usecase->stream.out->volume_r);
1711 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301712 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001713 }
1714 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001715 }
1716}
1717
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301718static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001719 struct audio_usecase *uc_info,
1720 snd_device_t snd_device)
1721{
1722 struct listnode *node;
1723 struct audio_usecase *usecase;
1724 bool switch_device[AUDIO_USECASE_MAX];
1725 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301726 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001727 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001728
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301729 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1730 snd_device);
1731 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301732
1733 /*
1734 * Make sure out devices is checked against out codec backend device and
1735 * also in devices against in codec backend. Checking out device against in
1736 * codec backend or vice versa causes issues.
1737 */
1738 if (uc_info->type == PCM_CAPTURE)
1739 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001740 /*
1741 * This function is to make sure that all the active capture usecases
1742 * are always routed to the same input sound device.
1743 * For example, if audio-record and voice-call usecases are currently
1744 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1745 * is received for voice call then we have to make sure that audio-record
1746 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1747 * because of the limitation that two devices cannot be enabled
1748 * at the same time if they share the same backend.
1749 */
1750 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1751 switch_device[i] = false;
1752
1753 list_for_each(node, &adev->usecase_list) {
1754 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301755 /*
1756 * TODO: Enhance below condition to handle BT sco/USB multi recording
1757 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001758 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001759 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301760 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301761 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301762 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301763 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001764 ((uc_info->type == VOICE_CALL &&
1765 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1766 platform_check_backends_match(snd_device,\
1767 usecase->in_snd_device)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001768 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001769 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1770 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001771 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001772 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001773 switch_device[usecase->id] = true;
1774 num_uc_to_switch++;
1775 }
1776 }
1777
1778 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001779 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001780
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301781 /* Make sure the previous devices to be disabled first and then enable the
1782 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001783 list_for_each(node, &adev->usecase_list) {
1784 usecase = node_to_item(node, struct audio_usecase, list);
1785 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001786 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001787 }
1788 }
1789
1790 list_for_each(node, &adev->usecase_list) {
1791 usecase = node_to_item(node, struct audio_usecase, list);
1792 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001793 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001794 }
1795 }
1796
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001797 /* Re-route all the usecases on the shared backend other than the
1798 specified usecase to new snd devices */
1799 list_for_each(node, &adev->usecase_list) {
1800 usecase = node_to_item(node, struct audio_usecase, list);
1801 /* Update the in_snd_device only before enabling the audio route */
1802 if (switch_device[usecase->id] ) {
1803 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001804 if (usecase->type != VOICE_CALL) {
1805 /* Update voc calibration before enabling VoIP route */
1806 if (usecase->type == VOIP_CALL)
1807 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001808 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001809 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301810 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001811 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001812 }
1813 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001814 }
1815}
1816
Mingming Yin3a941d42016-02-17 18:08:05 -08001817static void reset_hdmi_sink_caps(struct stream_out *out) {
1818 int i = 0;
1819
1820 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1821 out->supported_channel_masks[i] = 0;
1822 }
1823 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1824 out->supported_formats[i] = 0;
1825 }
1826 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1827 out->supported_sample_rates[i] = 0;
1828 }
1829}
1830
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001831/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001832static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001833{
Mingming Yin3a941d42016-02-17 18:08:05 -08001834 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001835 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001836
Mingming Yin3a941d42016-02-17 18:08:05 -08001837 reset_hdmi_sink_caps(out);
1838
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001839 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001840 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001841 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001842 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001843 }
1844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001845 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001846 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001847 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001848 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001849 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1850 case 6:
1851 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1852 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1853 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1854 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1855 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1856 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001857 break;
1858 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001859 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001860 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001861 break;
1862 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001863
1864 // check channel format caps
1865 i = 0;
1866 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1867 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1868 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1869 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1870 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1871 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1872 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1873 }
1874
Ben Romberger1aaaf862017-04-06 17:49:46 -07001875 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1876 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1877 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1878 }
1879
Mingming Yin3a941d42016-02-17 18:08:05 -08001880 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1881 ALOGV(":%s HDMI supports DTS format", __func__);
1882 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1883 }
1884
1885 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1886 ALOGV(":%s HDMI supports DTS HD format", __func__);
1887 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1888 }
1889
Naresh Tanniru928f0862017-04-07 16:44:23 -07001890 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1891 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1892 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1893 }
1894
Mingming Yin3a941d42016-02-17 18:08:05 -08001895
1896 // check sample rate caps
1897 i = 0;
1898 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1899 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1900 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1901 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1902 }
1903 }
1904
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001905 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001906}
1907
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001908static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1909 uint32_t *supported_sample_rates __unused,
1910 uint32_t max_rates __unused)
1911{
1912 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1913 supported_sample_rates,
1914 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301915 ssize_t i = 0;
1916
1917 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001918 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1919 supported_sample_rates[i]);
1920 }
1921 return count;
1922}
1923
1924static inline int read_usb_sup_channel_masks(bool is_playback,
1925 audio_channel_mask_t *supported_channel_masks,
1926 uint32_t max_masks)
1927{
1928 int channels = audio_extn_usb_get_max_channels(is_playback);
1929 int channel_count;
1930 uint32_t num_masks = 0;
1931 if (channels > MAX_HIFI_CHANNEL_COUNT)
1932 channels = MAX_HIFI_CHANNEL_COUNT;
1933
1934 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001935 // start from 2 channels as framework currently doesn't support mono.
1936 if (channels >= FCC_2) {
1937 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1938 }
1939 for (channel_count = FCC_2;
1940 channel_count <= channels && num_masks < max_masks;
1941 ++channel_count) {
1942 supported_channel_masks[num_masks++] =
1943 audio_channel_mask_for_index_assignment_from_count(channel_count);
1944 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001945 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001946 // For capture we report all supported channel masks from 1 channel up.
1947 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001948 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1949 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001950 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1951 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1952 if (channel_count <= FCC_2) {
1953 mask = audio_channel_in_mask_from_count(channel_count);
1954 supported_channel_masks[num_masks++] = mask;
1955 }
1956 const audio_channel_mask_t index_mask =
1957 audio_channel_mask_for_index_assignment_from_count(channel_count);
1958 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1959 supported_channel_masks[num_masks++] = index_mask;
1960 }
1961 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001962 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301963
vincenttewf51c94e2019-05-07 10:28:53 +08001964 for (size_t i = 0; i < num_masks; ++i) {
1965 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1966 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301967 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001968 return num_masks;
1969}
1970
1971static inline int read_usb_sup_formats(bool is_playback __unused,
1972 audio_format_t *supported_formats,
1973 uint32_t max_formats __unused)
1974{
1975 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1976 switch (bitwidth) {
1977 case 24:
1978 // XXX : usb.c returns 24 for s24 and s24_le?
1979 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1980 break;
1981 case 32:
1982 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1983 break;
1984 case 16:
1985 default :
1986 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1987 break;
1988 }
1989 ALOGV("%s: %s supported format %d", __func__,
1990 is_playback ? "P" : "C", bitwidth);
1991 return 1;
1992}
1993
1994static inline int read_usb_sup_params_and_compare(bool is_playback,
1995 audio_format_t *format,
1996 audio_format_t *supported_formats,
1997 uint32_t max_formats,
1998 audio_channel_mask_t *mask,
1999 audio_channel_mask_t *supported_channel_masks,
2000 uint32_t max_masks,
2001 uint32_t *rate,
2002 uint32_t *supported_sample_rates,
2003 uint32_t max_rates) {
2004 int ret = 0;
2005 int num_formats;
2006 int num_masks;
2007 int num_rates;
2008 int i;
2009
2010 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2011 max_formats);
2012 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2013 max_masks);
2014
2015 num_rates = read_usb_sup_sample_rates(is_playback,
2016 supported_sample_rates, max_rates);
2017
2018#define LUT(table, len, what, dflt) \
2019 for (i=0; i<len && (table[i] != what); i++); \
2020 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2021
2022 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2023 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2024 LUT(supported_sample_rates, num_rates, *rate, 0);
2025
2026#undef LUT
2027 return ret < 0 ? -EINVAL : 0; // HACK TBD
2028}
2029
Alexy Josephb1379942016-01-29 15:49:38 -08002030audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002031 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002032{
2033 struct audio_usecase *usecase;
2034 struct listnode *node;
2035
2036 list_for_each(node, &adev->usecase_list) {
2037 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002038 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002039 ALOGV("%s: usecase id %d", __func__, usecase->id);
2040 return usecase->id;
2041 }
2042 }
2043 return USECASE_INVALID;
2044}
2045
Alexy Josephb1379942016-01-29 15:49:38 -08002046struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002047 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002048{
2049 struct audio_usecase *usecase;
2050 struct listnode *node;
2051
2052 list_for_each(node, &adev->usecase_list) {
2053 usecase = node_to_item(node, struct audio_usecase, list);
2054 if (usecase->id == uc_id)
2055 return usecase;
2056 }
2057 return NULL;
2058}
2059
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302060/*
2061 * is a true native playback active
2062 */
2063bool audio_is_true_native_stream_active(struct audio_device *adev)
2064{
2065 bool active = false;
2066 int i = 0;
2067 struct listnode *node;
2068
2069 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2070 ALOGV("%s:napb: not in true mode or non hdphones device",
2071 __func__);
2072 active = false;
2073 goto exit;
2074 }
2075
2076 list_for_each(node, &adev->usecase_list) {
2077 struct audio_usecase *uc;
2078 uc = node_to_item(node, struct audio_usecase, list);
2079 struct stream_out *curr_out =
2080 (struct stream_out*) uc->stream.out;
2081
2082 if (curr_out && PCM_PLAYBACK == uc->type) {
2083 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2084 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2085 uc->id, curr_out->sample_rate,
2086 curr_out->bit_width,
2087 platform_get_snd_device_name(uc->out_snd_device));
2088
2089 if (is_offload_usecase(uc->id) &&
2090 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2091 active = true;
2092 ALOGD("%s:napb:native stream detected", __func__);
2093 }
2094 }
2095 }
2096exit:
2097 return active;
2098}
2099
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002100uint32_t adev_get_dsp_bit_width_enforce_mode()
2101{
2102 if (adev == NULL) {
2103 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2104 return 0;
2105 }
2106 return adev->dsp_bit_width_enforce_mode;
2107}
2108
2109static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2110{
2111 char value[PROPERTY_VALUE_MAX];
2112 int trial;
2113 uint32_t dsp_bit_width_enforce_mode = 0;
2114
2115 if (!mixer) {
2116 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2117 __func__);
2118 return 0;
2119 }
2120
2121 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2122 value, NULL) > 0) {
2123 trial = atoi(value);
2124 switch (trial) {
2125 case 16:
2126 dsp_bit_width_enforce_mode = 16;
2127 break;
2128 case 24:
2129 dsp_bit_width_enforce_mode = 24;
2130 break;
2131 case 32:
2132 dsp_bit_width_enforce_mode = 32;
2133 break;
2134 default:
2135 dsp_bit_width_enforce_mode = 0;
2136 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2137 break;
2138 }
2139 }
2140
2141 return dsp_bit_width_enforce_mode;
2142}
2143
2144static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2145 uint32_t enforce_mode,
2146 bool enable)
2147{
2148 struct mixer_ctl *ctl = NULL;
2149 const char *mixer_ctl_name = "ASM Bit Width";
2150 uint32_t asm_bit_width_mode = 0;
2151
2152 if (enforce_mode == 0) {
2153 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2154 return;
2155 }
2156
2157 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2158 if (!ctl) {
2159 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2160 __func__, mixer_ctl_name);
2161 return;
2162 }
2163
2164 if (enable)
2165 asm_bit_width_mode = enforce_mode;
2166 else
2167 asm_bit_width_mode = 0;
2168
2169 ALOGV("%s DSP bit width feature status is %d width=%d",
2170 __func__, enable, asm_bit_width_mode);
2171 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2172 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2173 asm_bit_width_mode);
2174
2175 return;
2176}
2177
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302178/*
2179 * if native DSD playback active
2180 */
2181bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2182{
2183 bool active = false;
2184 struct listnode *node = NULL;
2185 struct audio_usecase *uc = NULL;
2186 struct stream_out *curr_out = NULL;
2187
2188 list_for_each(node, &adev->usecase_list) {
2189 uc = node_to_item(node, struct audio_usecase, list);
2190 curr_out = (struct stream_out*) uc->stream.out;
2191
2192 if (curr_out && PCM_PLAYBACK == uc->type &&
2193 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2194 active = true;
2195 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302196 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302197 }
2198 }
2199 return active;
2200}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302201
2202static bool force_device_switch(struct audio_usecase *usecase)
2203{
2204 bool ret = false;
2205 bool is_it_true_mode = false;
2206
Zhou Song30f2c3e2018-02-08 14:02:15 +08002207 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302208 usecase->type == TRANSCODE_LOOPBACK_RX ||
2209 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002210 return false;
2211 }
2212
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002213 if(usecase->stream.out == NULL) {
2214 ALOGE("%s: stream.out is NULL", __func__);
2215 return false;
2216 }
2217
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302218 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002219 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2220 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2221 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302222 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2223 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2224 (!is_it_true_mode && adev->native_playback_enabled)){
2225 ret = true;
2226 ALOGD("napb: time to toggle native mode");
2227 }
2228 }
2229
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302230 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302231 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2232 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002233 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302234 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302235 ALOGD("Force a2dp device switch to update new encoder config");
2236 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002237 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302238
Florian Pfister1a84f312018-07-19 14:38:18 +02002239 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302240 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2241 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002242 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302243 return ret;
2244}
2245
Aalique Grahame22e49102018-12-18 14:23:57 -08002246static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2247{
2248 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2249}
2250
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302251bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2252{
2253 bool ret=false;
2254 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2255 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2256 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2257 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2258 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2259 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2260 ret = true;
2261
2262 return ret;
2263}
2264
2265bool is_a2dp_device(snd_device_t out_snd_device)
2266{
2267 bool ret=false;
2268 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2269 ret = true;
2270
2271 return ret;
2272}
2273
2274bool is_bt_soc_on(struct audio_device *adev)
2275{
2276 struct mixer_ctl *ctl;
2277 char *mixer_ctl_name = "BT SOC status";
2278 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2279 bool bt_soc_status = true;
2280 if (!ctl) {
2281 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2282 __func__, mixer_ctl_name);
2283 /*This is to ensure we dont break targets which dont have the kernel change*/
2284 return true;
2285 }
2286 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2287 ALOGD("BT SOC status: %d",bt_soc_status);
2288 return bt_soc_status;
2289}
2290
2291int out_standby_l(struct audio_stream *stream);
2292
Eric Laurent637e2d42018-11-15 12:24:31 -08002293struct stream_in *adev_get_active_input(const struct audio_device *adev)
2294{
2295 struct listnode *node;
2296 struct stream_in *last_active_in = NULL;
2297
2298 /* Get last added active input.
2299 * TODO: We may use a priority mechanism to pick highest priority active source */
2300 list_for_each(node, &adev->usecase_list)
2301 {
2302 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2303 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2304 last_active_in = usecase->stream.in;
2305 }
2306
2307 return last_active_in;
2308}
2309
2310struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2311{
2312 struct listnode *node;
2313
2314 /* First check active inputs with voice communication source and then
2315 * any input if audio mode is in communication */
2316 list_for_each(node, &adev->usecase_list)
2317 {
2318 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2319 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2320 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2321 return usecase->stream.in;
2322 }
2323 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2324 return adev_get_active_input(adev);
2325
2326 return NULL;
2327}
2328
Carter Hsu2e429db2019-05-14 18:50:52 +08002329/*
2330 * Aligned with policy.h
2331 */
2332static inline int source_priority(int inputSource)
2333{
2334 switch (inputSource) {
2335 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2336 return 9;
2337 case AUDIO_SOURCE_CAMCORDER:
2338 return 8;
2339 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2340 return 7;
2341 case AUDIO_SOURCE_UNPROCESSED:
2342 return 6;
2343 case AUDIO_SOURCE_MIC:
2344 return 5;
2345 case AUDIO_SOURCE_ECHO_REFERENCE:
2346 return 4;
2347 case AUDIO_SOURCE_FM_TUNER:
2348 return 3;
2349 case AUDIO_SOURCE_VOICE_RECOGNITION:
2350 return 2;
2351 case AUDIO_SOURCE_HOTWORD:
2352 return 1;
2353 default:
2354 break;
2355 }
2356 return 0;
2357}
2358
2359static struct stream_in *get_priority_input(struct audio_device *adev)
2360{
2361 struct listnode *node;
2362 struct audio_usecase *usecase;
2363 int last_priority = 0, priority;
2364 struct stream_in *priority_in = NULL;
2365 struct stream_in *in;
2366
2367 list_for_each(node, &adev->usecase_list) {
2368 usecase = node_to_item(node, struct audio_usecase, list);
2369 if (usecase->type == PCM_CAPTURE) {
2370 in = usecase->stream.in;
2371 if (!in)
2372 continue;
2373 priority = source_priority(in->source);
2374
2375 if (priority > last_priority) {
2376 last_priority = priority;
2377 priority_in = in;
2378 }
2379 }
2380 }
2381 return priority_in;
2382}
2383
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002384int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002385{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002386 snd_device_t out_snd_device = SND_DEVICE_NONE;
2387 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002388 struct audio_usecase *usecase = NULL;
2389 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002390 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002391 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302392 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002393 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002394 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002395
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302396 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2397
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002398 usecase = get_usecase_from_list(adev, uc_id);
2399 if (usecase == NULL) {
2400 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2401 return -EINVAL;
2402 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002403
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002404 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002405 (usecase->type == VOIP_CALL) ||
2406 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302407 if(usecase->stream.out == NULL) {
2408 ALOGE("%s: stream.out is NULL", __func__);
2409 return -EINVAL;
2410 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002411 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002412 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002413 in_snd_device = platform_get_input_snd_device(adev->platform,
2414 NULL,
2415 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002416 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302417 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302418 if (usecase->stream.inout == NULL) {
2419 ALOGE("%s: stream.inout is NULL", __func__);
2420 return -EINVAL;
2421 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302422 stream_out.devices = usecase->stream.inout->out_config.devices;
2423 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2424 stream_out.format = usecase->stream.inout->out_config.format;
2425 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2426 out_snd_device = platform_get_output_snd_device(adev->platform,
2427 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302428 usecase->devices = out_snd_device;
2429 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2430 if (usecase->stream.inout == NULL) {
2431 ALOGE("%s: stream.inout is NULL", __func__);
2432 return -EINVAL;
2433 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002434 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302435 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002436 } else {
2437 /*
2438 * If the voice call is active, use the sound devices of voice call usecase
2439 * so that it would not result any device switch. All the usecases will
2440 * be switched to new device when select_devices() is called for voice call
2441 * usecase. This is to avoid switching devices for voice call when
2442 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002443 * choose voice call device only if the use case device is
2444 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002445 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002446 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002447 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002448 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002449 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2450 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302451 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2452 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002453 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2454 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002455 in_snd_device = vc_usecase->in_snd_device;
2456 out_snd_device = vc_usecase->out_snd_device;
2457 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002458 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002459 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002460 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002461 if ((voip_usecase != NULL) &&
2462 (usecase->type == PCM_PLAYBACK) &&
2463 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002464 out_snd_device_backend_match = platform_check_backends_match(
2465 voip_usecase->out_snd_device,
2466 platform_get_output_snd_device(
2467 adev->platform,
2468 usecase->stream.out));
2469 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002470 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002471 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2472 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002473 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002474 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002475 in_snd_device = voip_usecase->in_snd_device;
2476 out_snd_device = voip_usecase->out_snd_device;
2477 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002478 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002479 hfp_ucid = audio_extn_hfp_get_usecase();
2480 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002481 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002482 in_snd_device = hfp_usecase->in_snd_device;
2483 out_snd_device = hfp_usecase->out_snd_device;
2484 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002485 }
2486 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302487 if (usecase->stream.out == NULL) {
2488 ALOGE("%s: stream.out is NULL", __func__);
2489 return -EINVAL;
2490 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002491 usecase->devices = usecase->stream.out->devices;
2492 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002493 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002494 struct stream_out *voip_out = adev->primary_output;
2495 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002496 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002497 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002498 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002499
Eric Laurent637e2d42018-11-15 12:24:31 -08002500 if (voip_usecase)
2501 voip_out = voip_usecase->stream.out;
2502
2503 if (usecase->stream.out == voip_out && voip_in != NULL)
2504 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002505 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002506 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302507 if (usecase->stream.in == NULL) {
2508 ALOGE("%s: stream.in is NULL", __func__);
2509 return -EINVAL;
2510 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002511 usecase->devices = usecase->stream.in->device;
2512 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002513 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002514 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002515 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002516 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002517
2518 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002519 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2520 USECASE_AUDIO_PLAYBACK_VOIP);
2521
Carter Hsu2e429db2019-05-14 18:50:52 +08002522 usecase->stream.in->enable_ec_port = false;
2523
Eric Laurent637e2d42018-11-15 12:24:31 -08002524 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2525 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2526 } else if (voip_usecase) {
2527 out_device = voip_usecase->stream.out->devices;
2528 } else if (adev->primary_output &&
2529 !adev->primary_output->standby) {
2530 out_device = adev->primary_output->devices;
2531 } else {
2532 /* forcing speaker o/p device to get matching i/p pair
2533 in case o/p is not routed from same primary HAL */
2534 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2535 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002536 priority_in = voip_in;
2537 } else {
2538 /* get the input with the highest priority source*/
2539 priority_in = get_priority_input(adev);
2540
2541 if (!priority_in)
2542 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002543 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002544
Eric Laurent637e2d42018-11-15 12:24:31 -08002545 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002546 priority_in,
Eric Laurent637e2d42018-11-15 12:24:31 -08002547 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002548 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002549 }
2550 }
2551
2552 if (out_snd_device == usecase->out_snd_device &&
2553 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302554
2555 if (!force_device_switch(usecase))
2556 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002557 }
2558
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302559 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002560 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302561 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2562 return 0;
2563 }
2564
Aalique Grahame22e49102018-12-18 14:23:57 -08002565 if (out_snd_device != SND_DEVICE_NONE &&
2566 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2567 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2568 __func__,
2569 use_case_table[uc_id],
2570 adev->last_logged_snd_device[uc_id][0],
2571 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2572 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2573 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2574 -1,
2575 out_snd_device,
2576 platform_get_snd_device_name(out_snd_device),
2577 platform_get_snd_device_acdb_id(out_snd_device));
2578 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2579 }
2580 if (in_snd_device != SND_DEVICE_NONE &&
2581 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2582 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2583 __func__,
2584 use_case_table[uc_id],
2585 adev->last_logged_snd_device[uc_id][1],
2586 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2587 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2588 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2589 -1,
2590 in_snd_device,
2591 platform_get_snd_device_name(in_snd_device),
2592 platform_get_snd_device_acdb_id(in_snd_device));
2593 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2594 }
2595
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 /*
2598 * Limitation: While in call, to do a device switch we need to disable
2599 * and enable both RX and TX devices though one of them is same as current
2600 * device.
2601 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002602 if ((usecase->type == VOICE_CALL) &&
2603 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2604 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002605 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002606 }
2607
2608 if (((usecase->type == VOICE_CALL) ||
2609 (usecase->type == VOIP_CALL)) &&
2610 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2611 /* Disable sidetone only if voice/voip call already exists */
2612 if (voice_is_call_state_active(adev) ||
2613 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002614 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002615
2616 /* Disable aanc only if voice call exists */
2617 if (voice_is_call_state_active(adev))
2618 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002619 }
2620
Aalique Grahame22e49102018-12-18 14:23:57 -08002621 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2622 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002623 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302624 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002625 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2626 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2627 else
2628 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302629 }
2630
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002631 /* Disable current sound devices */
2632 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002633 disable_audio_route(adev, usecase);
2634 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002635 }
2636
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002637 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002638 disable_audio_route(adev, usecase);
2639 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002640 }
2641
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002642 /* Applicable only on the targets that has external modem.
2643 * New device information should be sent to modem before enabling
2644 * the devices to reduce in-call device switch time.
2645 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002646 if ((usecase->type == VOICE_CALL) &&
2647 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2648 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002649 status = platform_switch_voice_call_enable_device_config(adev->platform,
2650 out_snd_device,
2651 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002652 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002653
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002654 /* Enable new sound devices */
2655 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002656 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302657 if (platform_check_codec_asrc_support(adev->platform))
2658 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002659 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002660 }
2661
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002662 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302663 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002664 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002665 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002666
Avinash Vaish71a8b972014-07-24 15:36:33 +05302667 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002668 status = platform_switch_voice_call_device_post(adev->platform,
2669 out_snd_device,
2670 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302671 enable_audio_route_for_voice_usecases(adev, usecase);
2672 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002673
sangwoo170731f2013-06-08 15:36:36 +09002674 usecase->in_snd_device = in_snd_device;
2675 usecase->out_snd_device = out_snd_device;
2676
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302677 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2678 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302679 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002680 if ((24 == usecase->stream.out->bit_width) &&
2681 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2682 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2683 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2684 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2685 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2686 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2687 /*
2688 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2689 * configured device sample rate, if not update the COPP rate to be equal to the
2690 * device sample rate, else open COPP at stream sample rate
2691 */
2692 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2693 usecase->stream.out->sample_rate,
2694 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302695 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2696 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002697 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2698 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2699 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2700 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002701 }
2702 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002703
Weiyin Jiangcdece202019-07-08 16:13:16 +08002704 /* Notify device change info to effect clients registered */
2705 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002706 audio_extn_gef_notify_device_config(
2707 usecase->stream.out->devices,
2708 usecase->stream.out->channel_mask,
2709 usecase->stream.out->app_type_cfg.sample_rate,
2710 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302711 }
sangwoo170731f2013-06-08 15:36:36 +09002712
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002713 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002714
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002715 /* If input stream is already running then effect needs to be
2716 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002717 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002718 check_and_enable_effect(adev);
2719
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002720 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002721 /* Enable aanc only if voice call exists */
2722 if (voice_is_call_state_active(adev))
2723 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2724
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002725 /* Enable sidetone only if other voice/voip call already exists */
2726 if (voice_is_call_state_active(adev) ||
2727 voice_extn_compress_voip_is_started(adev))
2728 voice_set_sidetone(adev, out_snd_device, true);
2729 }
2730
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002731 /* Applicable only on the targets that has external modem.
2732 * Enable device command should be sent to modem only after
2733 * enabling voice call mixer controls
2734 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002735 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002736 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2737 out_snd_device,
2738 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302739
2740 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002741 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302742 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002743 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302744 if (is_bt_soc_on(adev) == false){
2745 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002746 if (in->pcm != NULL)
2747 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302748 }
2749 }
2750 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2751 && usecase->stream.out->started) {
2752 if (is_bt_soc_on(adev) == false) {
2753 ALOGD("BT SCO/A2DP disconnected while in connection");
2754 out_standby_l(&usecase->stream.out->stream.common);
2755 }
2756 }
2757 } else if ((usecase->stream.out != NULL) &&
2758 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302759 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2760 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302761 usecase->stream.out->started) {
2762 if (is_bt_soc_on(adev) == false) {
2763 ALOGD("BT SCO/A2dp disconnected while in connection");
2764 out_standby_l(&usecase->stream.out->stream.common);
2765 }
2766 }
2767 }
2768
Yung Ti Su70cb8242018-06-22 17:38:47 +08002769 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002770 struct stream_out *voip_out = voip_usecase->stream.out;
2771 audio_extn_utils_send_app_type_gain(adev,
2772 voip_out->app_type_cfg.app_type,
2773 &voip_out->app_type_cfg.gain[0]);
2774 }
2775
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302776 ALOGD("%s: done",__func__);
2777
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002778 return status;
2779}
2780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781static int stop_input_stream(struct stream_in *in)
2782{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302783 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002784 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302785
2786 if (in == NULL) {
2787 ALOGE("%s: stream_in ptr is NULL", __func__);
2788 return -EINVAL;
2789 }
2790
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002791 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002792 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002793
Eric Laurent994a6932013-07-17 11:51:42 -07002794 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002795 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002796 uc_info = get_usecase_from_list(adev, in->usecase);
2797 if (uc_info == NULL) {
2798 ALOGE("%s: Could not find the usecase (%d) in the list",
2799 __func__, in->usecase);
2800 return -EINVAL;
2801 }
2802
Carter Hsu2e429db2019-05-14 18:50:52 +08002803 priority_in = get_priority_input(adev);
2804
Derek Chenea197282019-01-07 17:35:01 -08002805 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2806 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002807
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002808 /* Close in-call recording streams */
2809 voice_check_and_stop_incall_rec_usecase(adev, in);
2810
Eric Laurent150dbfe2013-02-27 14:31:02 -08002811 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002812 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002813
2814 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002815 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002816
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05302817 if (is_loopback_input_device(in->device))
2818 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
2819
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002820 list_remove(&uc_info->list);
2821 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822
Carter Hsu2e429db2019-05-14 18:50:52 +08002823 if (priority_in == in) {
2824 priority_in = get_priority_input(adev);
2825 if (priority_in)
2826 select_devices(adev, priority_in->usecase);
2827 }
2828
Vatsal Buchac09ae062018-11-14 13:25:08 +05302829 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002830 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002831 return ret;
2832}
2833
2834int start_input_stream(struct stream_in *in)
2835{
2836 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002837 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002838 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302839
2840 if (in == NULL) {
2841 ALOGE("%s: stream_in ptr is NULL", __func__);
2842 return -EINVAL;
2843 }
2844
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002845 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002846 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002847 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002848
Mingming Yin2664a5b2015-09-03 10:53:11 -07002849 if (get_usecase_from_list(adev, usecase) == NULL)
2850 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302851 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2852 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002853
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302854 if (CARD_STATUS_OFFLINE == in->card_status||
2855 CARD_STATUS_OFFLINE == adev->card_status) {
2856 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302857 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302858 goto error_config;
2859 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302860
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302861 if (audio_is_bluetooth_sco_device(in->device)) {
2862 if (!adev->bt_sco_on) {
2863 ALOGE("%s: SCO profile is not ready, return error", __func__);
2864 ret = -EIO;
2865 goto error_config;
2866 }
2867 }
2868
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002869 /* Check if source matches incall recording usecase criteria */
2870 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2871 if (ret)
2872 goto error_config;
2873 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002874 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2875
2876 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2877 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2878 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002879 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002880 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002881
Eric Laurentb23d5282013-05-14 15:27:20 -07002882 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883 if (in->pcm_device_id < 0) {
2884 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2885 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002886 ret = -EINVAL;
2887 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002888 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002889
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002890 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002891
2892 if (!uc_info) {
2893 ret = -ENOMEM;
2894 goto error_config;
2895 }
2896
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002897 uc_info->id = in->usecase;
2898 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002899 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002900 uc_info->devices = in->device;
2901 uc_info->in_snd_device = SND_DEVICE_NONE;
2902 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002903
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002904 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002905 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302906 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2907 adev->perf_lock_opts,
2908 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002909 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002910
Derek Chenea197282019-01-07 17:35:01 -08002911 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2912 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002913
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05302914 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
2915
Haynes Mathew George16081042017-05-31 17:16:49 -07002916 if (audio_extn_cin_attached_usecase(in->usecase)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05302917 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302918 if (ret)
2919 goto error_open;
2920 else
2921 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002922 }
2923
Haynes Mathew George16081042017-05-31 17:16:49 -07002924 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002925 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002926 ALOGE("%s: pcm stream not ready", __func__);
2927 goto error_open;
2928 }
2929 ret = pcm_start(in->pcm);
2930 if (ret < 0) {
2931 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2932 goto error_open;
2933 }
2934 } else {
2935 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2936 unsigned int pcm_open_retry_count = 0;
2937
2938 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2939 flags |= PCM_MMAP | PCM_NOIRQ;
2940 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2941 } else if (in->realtime) {
2942 flags |= PCM_MMAP | PCM_NOIRQ;
2943 }
2944
Garmond Leunge2433c32017-09-28 21:51:22 -07002945 if (audio_extn_ffv_get_stream() == in) {
2946 ALOGD("%s: ffv stream, update pcm config", __func__);
2947 audio_extn_ffv_update_pcm_config(&config);
2948 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002949 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2950 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2951
2952 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002953 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002954 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002955 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002956 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302957 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302958 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2959 adev->card_status = CARD_STATUS_OFFLINE;
2960 in->card_status = CARD_STATUS_OFFLINE;
2961 ret = -EIO;
2962 goto error_open;
2963 }
2964
Haynes Mathew George16081042017-05-31 17:16:49 -07002965 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2966 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2967 if (in->pcm != NULL) {
2968 pcm_close(in->pcm);
2969 in->pcm = NULL;
2970 }
2971 if (pcm_open_retry_count-- == 0) {
2972 ret = -EIO;
2973 goto error_open;
2974 }
2975 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2976 continue;
2977 }
2978 break;
2979 }
2980
2981 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002982 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002983 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002984 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002985 if (ret < 0) {
2986 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2987 pcm_close(in->pcm);
2988 in->pcm = NULL;
2989 goto error_open;
2990 }
2991 register_in_stream(in);
2992 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002993 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002994 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002995 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002996 if (ret < 0) {
2997 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002998 pcm_close(in->pcm);
2999 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003000 goto error_open;
3001 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003002 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003003 }
3004
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003005 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003006 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3007 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003008
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303009 if (is_loopback_input_device(in->device))
3010 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3011
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303012done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003013 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303014 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003015 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303016 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003017 return ret;
3018
3019error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003020 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303021 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003022 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003023
Eric Laurentc8400632013-02-14 19:04:54 -08003024error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303025 /*
3026 * sleep 50ms to allow sufficient time for kernel
3027 * drivers to recover incases like SSR.
3028 */
3029 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003030 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303031 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003032 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003033}
3034
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003035void lock_input_stream(struct stream_in *in)
3036{
3037 pthread_mutex_lock(&in->pre_lock);
3038 pthread_mutex_lock(&in->lock);
3039 pthread_mutex_unlock(&in->pre_lock);
3040}
3041
3042void lock_output_stream(struct stream_out *out)
3043{
3044 pthread_mutex_lock(&out->pre_lock);
3045 pthread_mutex_lock(&out->lock);
3046 pthread_mutex_unlock(&out->pre_lock);
3047}
3048
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003049/* must be called with out->lock locked */
3050static int send_offload_cmd_l(struct stream_out* out, int command)
3051{
3052 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3053
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003054 if (!cmd) {
3055 ALOGE("failed to allocate mem for command 0x%x", command);
3056 return -ENOMEM;
3057 }
3058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059 ALOGVV("%s %d", __func__, command);
3060
3061 cmd->cmd = command;
3062 list_add_tail(&out->offload_cmd_list, &cmd->node);
3063 pthread_cond_signal(&out->offload_cond);
3064 return 0;
3065}
3066
3067/* must be called iwth out->lock locked */
3068static void stop_compressed_output_l(struct stream_out *out)
3069{
3070 out->offload_state = OFFLOAD_STATE_IDLE;
3071 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003072 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003073 if (out->compr != NULL) {
3074 compress_stop(out->compr);
3075 while (out->offload_thread_blocked) {
3076 pthread_cond_wait(&out->cond, &out->lock);
3077 }
3078 }
3079}
3080
Varun Balaraje49253e2017-07-06 19:48:56 +05303081bool is_interactive_usecase(audio_usecase_t uc_id)
3082{
3083 unsigned int i;
3084 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3085 if (uc_id == interactive_usecases[i])
3086 return true;
3087 }
3088 return false;
3089}
3090
3091static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3092{
3093 audio_usecase_t ret_uc = USECASE_INVALID;
3094 unsigned int intract_uc_index;
3095 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3096
3097 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3098 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3099 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3100 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3101 ret_uc = interactive_usecases[intract_uc_index];
3102 break;
3103 }
3104 }
3105
3106 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3107 return ret_uc;
3108}
3109
3110static void free_interactive_usecase(struct audio_device *adev,
3111 audio_usecase_t uc_id)
3112{
3113 unsigned int interact_uc_index;
3114 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3115
3116 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3117 if (interactive_usecases[interact_uc_index] == uc_id) {
3118 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3119 break;
3120 }
3121 }
3122 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3123}
3124
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003125bool is_offload_usecase(audio_usecase_t uc_id)
3126{
3127 unsigned int i;
3128 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3129 if (uc_id == offload_usecases[i])
3130 return true;
3131 }
3132 return false;
3133}
3134
Dhananjay Kumarac341582017-02-23 23:42:25 +05303135static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003136{
vivek mehta446c3962015-09-14 10:57:35 -07003137 audio_usecase_t ret_uc = USECASE_INVALID;
3138 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003139 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003140 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303141 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003142 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3143 else
3144 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003145
vivek mehta446c3962015-09-14 10:57:35 -07003146 pthread_mutex_lock(&adev->lock);
3147 if (get_usecase_from_list(adev, ret_uc) != NULL)
3148 ret_uc = USECASE_INVALID;
3149 pthread_mutex_unlock(&adev->lock);
3150
3151 return ret_uc;
3152 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003153
3154 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003155 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3156 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3157 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3158 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003159 break;
3160 }
3161 }
vivek mehta446c3962015-09-14 10:57:35 -07003162
3163 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3164 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003165}
3166
3167static void free_offload_usecase(struct audio_device *adev,
3168 audio_usecase_t uc_id)
3169{
vivek mehta446c3962015-09-14 10:57:35 -07003170 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003171 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003172
3173 if (!adev->multi_offload_enable)
3174 return;
3175
3176 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3177 if (offload_usecases[offload_uc_index] == uc_id) {
3178 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003179 break;
3180 }
3181 }
3182 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3183}
3184
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003185static void *offload_thread_loop(void *context)
3186{
3187 struct stream_out *out = (struct stream_out *) context;
3188 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003189 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003190
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003191 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003192 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003193 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3194
3195 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003196 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003197 out->offload_state = OFFLOAD_STATE_IDLE;
3198 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003199 for (;;) {
3200 struct offload_cmd *cmd = NULL;
3201 stream_callback_event_t event;
3202 bool send_callback = false;
3203
3204 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3205 __func__, list_empty(&out->offload_cmd_list),
3206 out->offload_state);
3207 if (list_empty(&out->offload_cmd_list)) {
3208 ALOGV("%s SLEEPING", __func__);
3209 pthread_cond_wait(&out->offload_cond, &out->lock);
3210 ALOGV("%s RUNNING", __func__);
3211 continue;
3212 }
3213
3214 item = list_head(&out->offload_cmd_list);
3215 cmd = node_to_item(item, struct offload_cmd, node);
3216 list_remove(item);
3217
3218 ALOGVV("%s STATE %d CMD %d out->compr %p",
3219 __func__, out->offload_state, cmd->cmd, out->compr);
3220
3221 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3222 free(cmd);
3223 break;
3224 }
3225
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003226 // allow OFFLOAD_CMD_ERROR reporting during standby
3227 // this is needed to handle failures during compress_open
3228 // Note however that on a pause timeout, the stream is closed
3229 // and no offload usecase will be active. Therefore this
3230 // special case is needed for compress_open failures alone
3231 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3232 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003233 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003234 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003235 pthread_cond_signal(&out->cond);
3236 continue;
3237 }
3238 out->offload_thread_blocked = true;
3239 pthread_mutex_unlock(&out->lock);
3240 send_callback = false;
3241 switch(cmd->cmd) {
3242 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003243 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003244 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003245 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003246 send_callback = true;
3247 event = STREAM_CBK_EVENT_WRITE_READY;
3248 break;
3249 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003250 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303251 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003252 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303253 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003254 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303255 if (ret < 0)
3256 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303257 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303258 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003259 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003260 else
3261 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003262 if (-ENETRESET != ret && !(-EINTR == ret &&
3263 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303264 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303265 pthread_mutex_lock(&out->lock);
3266 out->send_new_metadata = 1;
3267 out->send_next_track_params = true;
3268 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303269 event = STREAM_CBK_EVENT_DRAIN_READY;
3270 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3271 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303272 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003273 break;
3274 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003275 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003276 ret = compress_drain(out->compr);
3277 ALOGD("copl(%p):out of compress_drain", out);
3278 // EINTR check avoids drain interruption due to SSR
3279 if (-ENETRESET != ret && !(-EINTR == ret &&
3280 CARD_STATUS_OFFLINE == out->card_status)) {
3281 send_callback = true;
3282 event = STREAM_CBK_EVENT_DRAIN_READY;
3283 } else
3284 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003285 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303286 case OFFLOAD_CMD_ERROR:
3287 ALOGD("copl(%p): sending error callback to AF", out);
3288 send_callback = true;
3289 event = STREAM_CBK_EVENT_ERROR;
3290 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003291 default:
3292 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3293 break;
3294 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003295 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003296 out->offload_thread_blocked = false;
3297 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003298 if (send_callback && out->client_callback) {
3299 ALOGVV("%s: sending client_callback event %d", __func__, event);
3300 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003301 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003302 free(cmd);
3303 }
3304
3305 pthread_cond_signal(&out->cond);
3306 while (!list_empty(&out->offload_cmd_list)) {
3307 item = list_head(&out->offload_cmd_list);
3308 list_remove(item);
3309 free(node_to_item(item, struct offload_cmd, node));
3310 }
3311 pthread_mutex_unlock(&out->lock);
3312
3313 return NULL;
3314}
3315
3316static int create_offload_callback_thread(struct stream_out *out)
3317{
3318 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3319 list_init(&out->offload_cmd_list);
3320 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3321 offload_thread_loop, out);
3322 return 0;
3323}
3324
3325static int destroy_offload_callback_thread(struct stream_out *out)
3326{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003327 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003328 stop_compressed_output_l(out);
3329 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3330
3331 pthread_mutex_unlock(&out->lock);
3332 pthread_join(out->offload_thread, (void **) NULL);
3333 pthread_cond_destroy(&out->offload_cond);
3334
3335 return 0;
3336}
3337
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338static int stop_output_stream(struct stream_out *out)
3339{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303340 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341 struct audio_usecase *uc_info;
3342 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003343 bool has_voip_usecase =
3344 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003345
Eric Laurent994a6932013-07-17 11:51:42 -07003346 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003347 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348 uc_info = get_usecase_from_list(adev, out->usecase);
3349 if (uc_info == NULL) {
3350 ALOGE("%s: Could not find the usecase (%d) in the list",
3351 __func__, out->usecase);
3352 return -EINVAL;
3353 }
3354
Derek Chenea197282019-01-07 17:35:01 -08003355 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3356 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003357
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003358 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303359 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003360 if (adev->visualizer_stop_output != NULL)
3361 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003362
3363 audio_extn_dts_remove_state_notifier_node(out->usecase);
3364
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003365 if (adev->offload_effects_stop_output != NULL)
3366 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003367 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3368 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3369 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003370 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003371
Arun Mirpurief53ce52018-09-11 18:00:09 -07003372 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3373 voice_set_device_mute_flag(adev, false);
3374
Eric Laurent150dbfe2013-02-27 14:31:02 -08003375 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003376 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003377
3378 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003379 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003380
Aalique Grahame22e49102018-12-18 14:23:57 -08003381 audio_extn_extspk_update(adev->extspk);
3382
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003383 if (is_offload_usecase(out->usecase)) {
3384 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3385 adev->dsp_bit_width_enforce_mode,
3386 false);
3387 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003388 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3389 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3390 false);
3391
3392 if (ret != 0)
3393 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3394 /* default service interval was successfully updated,
3395 reopen USB backend with new service interval */
3396 ret = 0;
3397 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003398
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003399 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303400 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003401 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303402 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003403 ALOGV("Disable passthrough , reset mixer to pcm");
3404 /* NO_PASSTHROUGH */
3405 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003406 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003407 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3408 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003409
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303410 /* Must be called after removing the usecase from list */
3411 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303412 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303413
Manish Dewangan21a850a2017-08-14 12:03:55 +05303414 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003415 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3416 if (ret < 0)
3417 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3418 }
3419
juyuchen2d415992018-11-16 14:15:16 +08003420 /* 1) media + voip output routing to handset must route media back to
3421 speaker when voip stops.
3422 2) trigger voip input to reroute when voip output changes to
3423 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003424 if (has_voip_usecase ||
3425 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3426 struct listnode *node;
3427 struct audio_usecase *usecase;
3428 list_for_each(node, &adev->usecase_list) {
3429 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003430 if ((usecase->type == PCM_CAPTURE &&
3431 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3432 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003433 continue;
3434
3435 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3436 __func__, usecase->id, use_case_table[usecase->id],
3437 out->usecase, use_case_table[out->usecase]);
3438 select_devices(adev, usecase->id);
3439 }
3440 }
3441
Garmond Leung5fd0b552018-04-17 11:56:12 -07003442 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003443 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003444 return ret;
3445}
3446
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003447struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3448 unsigned int flags, unsigned int pcm_open_retry_count,
3449 struct pcm_config *config)
3450{
3451 struct pcm* pcm = NULL;
3452
3453 while (1) {
3454 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3455 if (pcm == NULL || !pcm_is_ready(pcm)) {
3456 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3457 if (pcm != NULL) {
3458 pcm_close(pcm);
3459 pcm = NULL;
3460 }
3461 if (pcm_open_retry_count-- == 0)
3462 return NULL;
3463
3464 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3465 continue;
3466 }
3467 break;
3468 }
3469
3470 if (pcm_is_ready(pcm)) {
3471 int ret = pcm_prepare(pcm);
3472 if (ret < 0) {
3473 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3474 pcm_close(pcm);
3475 pcm = NULL;
3476 }
3477 }
3478
3479 return pcm;
3480}
3481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003482int start_output_stream(struct stream_out *out)
3483{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003484 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003485 struct audio_usecase *uc_info;
3486 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003487 char mixer_ctl_name[128];
3488 struct mixer_ctl *ctl = NULL;
3489 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303490 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003491 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492
Haynes Mathew George380745d2017-10-04 15:27:45 -07003493 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003494 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3495 ret = -EINVAL;
3496 goto error_config;
3497 }
3498
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003499 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303500 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003501 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303502
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303503 if (CARD_STATUS_OFFLINE == out->card_status ||
3504 CARD_STATUS_OFFLINE == adev->card_status) {
3505 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303506 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303507 goto error_config;
3508 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303509
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303510 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003511 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003512 if (out->devices &
3513 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303514 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303515 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303516 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3517 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3518 ret = -EAGAIN;
3519 goto error_config;
3520 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303521 }
3522 }
3523 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303524 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3525 if (!adev->bt_sco_on) {
3526 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3527 //combo usecase just by pass a2dp
3528 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3529 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3530 } else {
3531 ALOGE("%s: SCO profile is not ready, return error", __func__);
3532 ret = -EAGAIN;
3533 goto error_config;
3534 }
3535 }
3536 }
3537
Eric Laurentb23d5282013-05-14 15:27:20 -07003538 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003539 if (out->pcm_device_id < 0) {
3540 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3541 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003542 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003543 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003544 }
3545
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003546 if (is_haptic_usecase) {
3547 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3548 if (adev->haptic_pcm_device_id < 0) {
3549 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3550 __func__, adev->haptic_pcm_device_id, out->usecase);
3551 ret = -EINVAL;
3552 goto error_config;
3553 }
3554 }
3555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003557
3558 if (!uc_info) {
3559 ret = -ENOMEM;
3560 goto error_config;
3561 }
3562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003563 uc_info->id = out->usecase;
3564 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003565 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003566 uc_info->devices = out->devices;
3567 uc_info->in_snd_device = SND_DEVICE_NONE;
3568 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003569
3570 /* This must be called before adding this usecase to the list */
3571 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3572 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3573 /* USB backend is not reopened immediately.
3574 This is eventually done as part of select_devices */
3575 }
3576
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003577 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003578
Wei Wangf7ca6c92017-11-21 14:51:20 -08003579 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303580 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3581 adev->perf_lock_opts,
3582 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303583
3584 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303585 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303586 if (audio_extn_passthru_is_enabled() &&
3587 audio_extn_passthru_is_passthrough_stream(out)) {
3588 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303589 }
3590 }
3591
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303592 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003593 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303594 if (!a2dp_combo) {
3595 check_a2dp_restore_l(adev, out, false);
3596 } else {
3597 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003598 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3599 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3600 else
3601 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303602 select_devices(adev, out->usecase);
3603 out->devices = dev;
3604 }
3605 } else {
3606 select_devices(adev, out->usecase);
3607 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003608
Arun Mirpurief53ce52018-09-11 18:00:09 -07003609 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3610 voice_set_device_mute_flag(adev, true);
3611
Derek Chenea197282019-01-07 17:35:01 -08003612 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3613 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003614
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003615 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3616 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003617
3618 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003619 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003620 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3621 ALOGE("%s: pcm stream not ready", __func__);
3622 goto error_open;
3623 }
3624 ret = pcm_start(out->pcm);
3625 if (ret < 0) {
3626 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3627 goto error_open;
3628 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003629 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003630 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003631 unsigned int flags = PCM_OUT;
3632 unsigned int pcm_open_retry_count = 0;
3633 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3634 flags |= PCM_MMAP | PCM_NOIRQ;
3635 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003636 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003637 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003638 } else
3639 flags |= PCM_MONOTONIC;
3640
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003641 if ((adev->vr_audio_mode_enabled) &&
3642 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3643 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3644 "PCM_Dev %d Topology", out->pcm_device_id);
3645 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3646 if (!ctl) {
3647 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3648 __func__, mixer_ctl_name);
3649 } else {
3650 //if success use ULLPP
3651 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3652 __func__, mixer_ctl_name, out->pcm_device_id);
3653 //There is a still a possibility that some sessions
3654 // that request for FAST|RAW when 3D audio is active
3655 //can go through ULLPP. Ideally we expects apps to
3656 //listen to audio focus and stop concurrent playback
3657 //Also, we will look for mode flag (voice_in_communication)
3658 //before enabling the realtime flag.
3659 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3660 }
3661 }
3662
Surendar Karka91fa3682018-07-02 18:12:12 +05303663 if (out->realtime)
3664 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3665 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3666
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003667 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3668 flags, pcm_open_retry_count,
3669 &(out->config));
3670 if (out->pcm == NULL) {
3671 ret = -EIO;
3672 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003673 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003674
3675 if (is_haptic_usecase) {
3676 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3677 adev->haptic_pcm_device_id,
3678 flags, pcm_open_retry_count,
3679 &(adev->haptics_config));
3680 // failure to open haptics pcm shouldnt stop audio,
3681 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003682
3683 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3684 ALOGD("%s: enable haptic audio synchronization", __func__);
3685 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3686 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003687 }
3688
Surendar Karka91fa3682018-07-02 18:12:12 +05303689 if (!out->realtime)
3690 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303691 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003692
Zhou Song2b8f28f2017-09-11 10:51:38 +08003693 // apply volume for voip playback after path is set up
3694 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3695 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303696 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3697 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303698 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3699 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003700 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3701 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303702 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003703 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003704 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303705 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003706 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3707 adev->dsp_bit_width_enforce_mode,
3708 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003710 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003711 out->compr = compress_open(adev->snd_card,
3712 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003713 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003714 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303715 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303716 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3717 adev->card_status = CARD_STATUS_OFFLINE;
3718 out->card_status = CARD_STATUS_OFFLINE;
3719 ret = -EIO;
3720 goto error_open;
3721 }
3722
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003723 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003724 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003725 compress_close(out->compr);
3726 out->compr = NULL;
3727 ret = -EIO;
3728 goto error_open;
3729 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303730 /* compress_open sends params of the track, so reset the flag here */
3731 out->is_compr_metadata_avail = false;
3732
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003733 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003734 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003735
Fred Oh3f43e742015-03-04 18:42:34 -08003736 /* Since small bufs uses blocking writes, a write will be blocked
3737 for the default max poll time (20s) in the event of an SSR.
3738 Reduce the poll time to observe and deal with SSR faster.
3739 */
Ashish Jain5106d362016-05-11 19:23:33 +05303740 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003741 compress_set_max_poll_wait(out->compr, 1000);
3742 }
3743
Manish Dewangan69426c82017-01-30 17:35:36 +05303744 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303745 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303746
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003747 audio_extn_dts_create_state_notifier_node(out->usecase);
3748 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3749 popcount(out->channel_mask),
3750 out->playback_started);
3751
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003752#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303753 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003754 audio_extn_dolby_send_ddp_endp_params(adev);
3755#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303756 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3757 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003758 if (adev->visualizer_start_output != NULL)
3759 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3760 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303761 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003762 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003763 }
Derek Chenf13dd492018-11-13 14:53:51 -08003764
3765 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
3766 /* Update cached volume from media to offload/direct stream */
3767 struct listnode *node = NULL;
3768 list_for_each(node, &adev->active_outputs_list) {
3769 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3770 streams_output_ctxt_t,
3771 list);
3772 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3773 out->volume_l = out_ctxt->output->volume_l;
3774 out->volume_r = out_ctxt->output->volume_r;
3775 }
3776 }
3777 out_set_compr_volume(&out->stream,
3778 out->volume_l, out->volume_r);
3779 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003780 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003781
3782 if (ret == 0) {
3783 register_out_stream(out);
3784 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003785 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3786 ALOGE("%s: pcm stream not ready", __func__);
3787 goto error_open;
3788 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003789 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003790 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003791 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003792 if (ret < 0)
3793 goto error_open;
3794 }
3795 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003796 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303797 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003798 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003799
vivek mehtad15d2bf2019-05-17 13:35:10 -07003800 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3801 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3802 audio_low_latency_hint_start();
3803 }
3804
Manish Dewangan21a850a2017-08-14 12:03:55 +05303805 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003806 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003807 if (ret < 0)
3808 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3809 }
3810
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003811 // consider a scenario where on pause lower layers are tear down.
3812 // so on resume, swap mixer control need to be sent only when
3813 // backend is active, hence rather than sending from enable device
3814 // sending it from start of streamtream
3815
3816 platform_set_swap_channels(adev, true);
3817
Haynes Mathew George380745d2017-10-04 15:27:45 -07003818 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303819 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003820 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003821error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003822 if (adev->haptic_pcm) {
3823 pcm_close(adev->haptic_pcm);
3824 adev->haptic_pcm = NULL;
3825 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003826 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303827 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003828 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003829error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303830 /*
3831 * sleep 50ms to allow sufficient time for kernel
3832 * drivers to recover incases like SSR.
3833 */
3834 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003835 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303836 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003837 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838}
3839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840static int check_input_parameters(uint32_t sample_rate,
3841 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003842 int channel_count,
3843 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003844{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003845 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003846
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303847 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3848 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3849 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003850 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003851 !audio_extn_compr_cap_format_supported(format) &&
3852 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003853 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003854
Aalique Grahame22e49102018-12-18 14:23:57 -08003855 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3856 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3857 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3858 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3859 return -EINVAL;
3860 }
3861
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003862 switch (channel_count) {
3863 case 1:
3864 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303865 case 3:
3866 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003867 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003868 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303869 case 10:
3870 case 12:
3871 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003872 break;
3873 default:
3874 ret = -EINVAL;
3875 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003876
3877 switch (sample_rate) {
3878 case 8000:
3879 case 11025:
3880 case 12000:
3881 case 16000:
3882 case 22050:
3883 case 24000:
3884 case 32000:
3885 case 44100:
3886 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003887 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303888 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003889 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303890 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003891 break;
3892 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003893 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003894 }
3895
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003896 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003897}
3898
Naresh Tanniru04f71882018-06-26 17:46:22 +05303899
3900/** Add a value in a list if not already present.
3901 * @return true if value was successfully inserted or already present,
3902 * false if the list is full and does not contain the value.
3903 */
3904static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3905 for (size_t i = 0; i < list_length; i++) {
3906 if (list[i] == value) return true; // value is already present
3907 if (list[i] == 0) { // no values in this slot
3908 list[i] = value;
3909 return true; // value inserted
3910 }
3911 }
3912 return false; // could not insert value
3913}
3914
3915/** Add channel_mask in supported_channel_masks if not already present.
3916 * @return true if channel_mask was successfully inserted or already present,
3917 * false if supported_channel_masks is full and does not contain channel_mask.
3918 */
3919static void register_channel_mask(audio_channel_mask_t channel_mask,
3920 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3921 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3922 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3923}
3924
3925/** Add format in supported_formats if not already present.
3926 * @return true if format was successfully inserted or already present,
3927 * false if supported_formats is full and does not contain format.
3928 */
3929static void register_format(audio_format_t format,
3930 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3931 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3932 "%s: stream can not declare supporting its format %x", __func__, format);
3933}
3934/** Add sample_rate in supported_sample_rates if not already present.
3935 * @return true if sample_rate was successfully inserted or already present,
3936 * false if supported_sample_rates is full and does not contain sample_rate.
3937 */
3938static void register_sample_rate(uint32_t sample_rate,
3939 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3940 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3941 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3942}
3943
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003944static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3945{
3946 uint32_t high = num1, low = num2, temp = 0;
3947
3948 if (!num1 || !num2)
3949 return 0;
3950
3951 if (num1 < num2) {
3952 high = num2;
3953 low = num1;
3954 }
3955
3956 while (low != 0) {
3957 temp = low;
3958 low = high % low;
3959 high = temp;
3960 }
3961 return (num1 * num2)/high;
3962}
3963
3964static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3965{
3966 uint32_t remainder = 0;
3967
3968 if (!multiplier)
3969 return num;
3970
3971 remainder = num % multiplier;
3972 if (remainder)
3973 num += (multiplier - remainder);
3974
3975 return num;
3976}
3977
Aalique Grahame22e49102018-12-18 14:23:57 -08003978static size_t get_stream_buffer_size(size_t duration_ms,
3979 uint32_t sample_rate,
3980 audio_format_t format,
3981 int channel_count,
3982 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003983{
3984 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003985 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986
Aalique Grahame22e49102018-12-18 14:23:57 -08003987 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003988 if (is_low_latency)
3989 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303990
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003991 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003992 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003993
Ralf Herzbd08d632018-09-28 15:50:49 +02003994 /* make sure the size is multiple of 32 bytes and additionally multiple of
3995 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003996 * At 48 kHz mono 16-bit PCM:
3997 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3998 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003999 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004000 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004001 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004002
4003 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004004}
4005
Aalique Grahame22e49102018-12-18 14:23:57 -08004006static size_t get_input_buffer_size(uint32_t sample_rate,
4007 audio_format_t format,
4008 int channel_count,
4009 bool is_low_latency)
4010{
4011 /* Don't know if USB HIFI in this context so use true to be conservative */
4012 if (check_input_parameters(sample_rate, format, channel_count,
4013 true /*is_usb_hifi */) != 0)
4014 return 0;
4015
4016 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4017 sample_rate,
4018 format,
4019 channel_count,
4020 is_low_latency);
4021}
4022
Derek Chenf6318be2017-06-12 17:16:24 -04004023size_t get_output_period_size(uint32_t sample_rate,
4024 audio_format_t format,
4025 int channel_count,
4026 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304027{
4028 size_t size = 0;
4029 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4030
4031 if ((duration == 0) || (sample_rate == 0) ||
4032 (bytes_per_sample == 0) || (channel_count == 0)) {
4033 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4034 bytes_per_sample, channel_count);
4035 return -EINVAL;
4036 }
4037
4038 size = (sample_rate *
4039 duration *
4040 bytes_per_sample *
4041 channel_count) / 1000;
4042 /*
4043 * To have same PCM samples for all channels, the buffer size requires to
4044 * be multiple of (number of channels * bytes per sample)
4045 * For writes to succeed, the buffer must be written at address which is multiple of 32
4046 */
4047 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4048
4049 return (size/(channel_count * bytes_per_sample));
4050}
4051
Zhou Song48453a02018-01-10 17:50:59 +08004052static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304053{
4054 uint64_t actual_frames_rendered = 0;
4055 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4056
4057 /* This adjustment accounts for buffering after app processor.
4058 * It is based on estimated DSP latency per use case, rather than exact.
4059 */
4060 int64_t platform_latency = platform_render_latency(out->usecase) *
4061 out->sample_rate / 1000000LL;
4062
Zhou Song48453a02018-01-10 17:50:59 +08004063 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304064 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4065 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4066 * hence only estimate.
4067 */
4068 int64_t signed_frames = out->written - kernel_buffer_size;
4069
4070 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
4071
Zhou Song48453a02018-01-10 17:50:59 +08004072 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304073 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004074 if (timestamp != NULL )
4075 *timestamp = out->writeAt;
4076 } else if (timestamp != NULL) {
4077 clock_gettime(CLOCK_MONOTONIC, timestamp);
4078 }
4079 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304080
4081 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
4082 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
4083 (long long int)out->written, (int)kernel_buffer_size,
4084 audio_bytes_per_sample(out->compr_config.codec->format),
4085 popcount(out->channel_mask));
4086
4087 return actual_frames_rendered;
4088}
4089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004090static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4091{
4092 struct stream_out *out = (struct stream_out *)stream;
4093
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004094 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004095}
4096
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004097static int out_set_sample_rate(struct audio_stream *stream __unused,
4098 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004099{
4100 return -ENOSYS;
4101}
4102
4103static size_t out_get_buffer_size(const struct audio_stream *stream)
4104{
4105 struct stream_out *out = (struct stream_out *)stream;
4106
Varun Balaraje49253e2017-07-06 19:48:56 +05304107 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304108 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304109 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304110 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4111 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4112 else
4113 return out->compr_config.fragment_size;
4114 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004115 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304116 else if (is_offload_usecase(out->usecase) &&
4117 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304118 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004119
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004120 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004121 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004122}
4123
4124static uint32_t out_get_channels(const struct audio_stream *stream)
4125{
4126 struct stream_out *out = (struct stream_out *)stream;
4127
4128 return out->channel_mask;
4129}
4130
4131static audio_format_t out_get_format(const struct audio_stream *stream)
4132{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004133 struct stream_out *out = (struct stream_out *)stream;
4134
4135 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004136}
4137
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004138static int out_set_format(struct audio_stream *stream __unused,
4139 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140{
4141 return -ENOSYS;
4142}
4143
4144static int out_standby(struct audio_stream *stream)
4145{
4146 struct stream_out *out = (struct stream_out *)stream;
4147 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004148 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004149
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304150 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4151 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004152
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004153 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004155 if (adev->adm_deregister_stream)
4156 adev->adm_deregister_stream(adev->adm_data, out->handle);
4157
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004158 if (is_offload_usecase(out->usecase))
4159 stop_compressed_output_l(out);
4160
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004161 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004162 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004163 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4164 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304165 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004166 pthread_mutex_unlock(&adev->lock);
4167 pthread_mutex_unlock(&out->lock);
4168 ALOGD("VOIP output entered standby");
4169 return 0;
4170 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004171 if (out->pcm) {
4172 pcm_close(out->pcm);
4173 out->pcm = NULL;
4174 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004175 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4176 do_stop = out->playback_started;
4177 out->playback_started = false;
4178 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004179 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004180 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304181 out->send_next_track_params = false;
4182 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004183 out->gapless_mdata.encoder_delay = 0;
4184 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004185 if (out->compr != NULL) {
4186 compress_close(out->compr);
4187 out->compr = NULL;
4188 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004189 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004190 if (do_stop) {
4191 stop_output_stream(out);
4192 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004193 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194 }
4195 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304196 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004197 return 0;
4198}
4199
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304200static int out_on_error(struct audio_stream *stream)
4201{
4202 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004203 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304204
4205 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004206 // always send CMD_ERROR for offload streams, this
4207 // is needed e.g. when SSR happens within compress_open
4208 // since the stream is active, offload_callback_thread is also active.
4209 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4210 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004211 }
4212 pthread_mutex_unlock(&out->lock);
4213
4214 status = out_standby(&out->stream.common);
4215
4216 lock_output_stream(out);
4217 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004218 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304219 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304220
4221 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4222 ALOGD("Setting previous card status if offline");
4223 out->prev_card_status_offline = true;
4224 }
4225
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304226 pthread_mutex_unlock(&out->lock);
4227
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004228 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304229}
4230
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304231/*
4232 *standby implementation without locks, assumes that the callee already
4233 *has taken adev and out lock.
4234 */
4235int out_standby_l(struct audio_stream *stream)
4236{
4237 struct stream_out *out = (struct stream_out *)stream;
4238 struct audio_device *adev = out->dev;
4239
4240 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4241 stream, out->usecase, use_case_table[out->usecase]);
4242
4243 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004244 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304245 if (adev->adm_deregister_stream)
4246 adev->adm_deregister_stream(adev->adm_data, out->handle);
4247
4248 if (is_offload_usecase(out->usecase))
4249 stop_compressed_output_l(out);
4250
4251 out->standby = true;
4252 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4253 voice_extn_compress_voip_close_output_stream(stream);
4254 out->started = 0;
4255 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004256 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304257 return 0;
4258 } else if (!is_offload_usecase(out->usecase)) {
4259 if (out->pcm) {
4260 pcm_close(out->pcm);
4261 out->pcm = NULL;
4262 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004263 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4264 if (adev->haptic_pcm) {
4265 pcm_close(adev->haptic_pcm);
4266 adev->haptic_pcm = NULL;
4267 }
4268
4269 if (adev->haptic_buffer != NULL) {
4270 free(adev->haptic_buffer);
4271 adev->haptic_buffer = NULL;
4272 adev->haptic_buffer_size = 0;
4273 }
4274 adev->haptic_pcm_device_id = 0;
4275 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304276 } else {
4277 ALOGD("copl(%p):standby", out);
4278 out->send_next_track_params = false;
4279 out->is_compr_metadata_avail = false;
4280 out->gapless_mdata.encoder_delay = 0;
4281 out->gapless_mdata.encoder_padding = 0;
4282 if (out->compr != NULL) {
4283 compress_close(out->compr);
4284 out->compr = NULL;
4285 }
4286 }
4287 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004288 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304289 }
4290 ALOGD("%s: exit", __func__);
4291 return 0;
4292}
4293
Aalique Grahame22e49102018-12-18 14:23:57 -08004294static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004295{
Aalique Grahame22e49102018-12-18 14:23:57 -08004296 struct stream_out *out = (struct stream_out *)stream;
4297
4298 // We try to get the lock for consistency,
4299 // but it isn't necessary for these variables.
4300 // If we're not in standby, we may be blocked on a write.
4301 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4302 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4303 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4304
4305 if (locked) {
4306 pthread_mutex_unlock(&out->lock);
4307 }
4308
4309 // dump error info
4310 (void)error_log_dump(
4311 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4312
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004313 return 0;
4314}
4315
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004316static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4317{
4318 int ret = 0;
4319 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004320
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004321 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004322 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004323 return -EINVAL;
4324 }
4325
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304326 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004327
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004328 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4329 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304330 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004331 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004332 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4333 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304334 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004335 }
4336
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004337 ALOGV("%s new encoder delay %u and padding %u", __func__,
4338 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4339
4340 return 0;
4341}
4342
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004343static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4344{
4345 return out == adev->primary_output || out == adev->voice_tx_output;
4346}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004347
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304348// note: this call is safe only if the stream_cb is
4349// removed first in close_output_stream (as is done now).
4350static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4351{
4352 if (!stream || !parms)
4353 return;
4354
4355 struct stream_out *out = (struct stream_out *)stream;
4356 struct audio_device *adev = out->dev;
4357
4358 card_status_t status;
4359 int card;
4360 if (parse_snd_card_status(parms, &card, &status) < 0)
4361 return;
4362
4363 pthread_mutex_lock(&adev->lock);
4364 bool valid_cb = (card == adev->snd_card);
4365 pthread_mutex_unlock(&adev->lock);
4366
4367 if (!valid_cb)
4368 return;
4369
4370 lock_output_stream(out);
4371 if (out->card_status != status)
4372 out->card_status = status;
4373 pthread_mutex_unlock(&out->lock);
4374
4375 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4376 use_case_table[out->usecase],
4377 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4378
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304379 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304380 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304381 if (voice_is_call_state_active(adev) &&
4382 out == adev->primary_output) {
4383 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4384 pthread_mutex_lock(&adev->lock);
4385 voice_stop_call(adev);
4386 adev->mode = AUDIO_MODE_NORMAL;
4387 pthread_mutex_unlock(&adev->lock);
4388 }
4389 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304390 return;
4391}
4392
Kevin Rocardfce19002017-08-07 19:21:36 -07004393static int get_alive_usb_card(struct str_parms* parms) {
4394 int card;
4395 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4396 !audio_extn_usb_alive(card)) {
4397 return card;
4398 }
4399 return -ENODEV;
4400}
4401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004402static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4403{
4404 struct stream_out *out = (struct stream_out *)stream;
4405 struct audio_device *adev = out->dev;
4406 struct str_parms *parms;
4407 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004408 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304409 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004410 bool reconfig = false;
4411 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004412
sangwoobc677242013-08-08 16:53:43 +09004413 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004414 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004415 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304416 if (!parms)
4417 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004418 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4419 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004420 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004421 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004422 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004424 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004425 * When HDMI cable is unplugged the music playback is paused and
4426 * the policy manager sends routing=0. But the audioflinger continues
4427 * to write data until standby time (3sec). As the HDMI core is
4428 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004429 * Avoid this by routing audio to speaker until standby.
4430 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004431 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4432 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304433 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004434 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4435 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004436 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304437 /*
4438 * When A2DP is disconnected the
4439 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004440 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304441 * (3sec). As BT is turned off, the write gets blocked.
4442 * Avoid this by routing audio to speaker until standby.
4443 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004444 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004445 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004446 !audio_extn_a2dp_source_is_ready() &&
4447 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304448 val = AUDIO_DEVICE_OUT_SPEAKER;
4449 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304450 /*
4451 * When USB headset is disconnected the music platback paused
4452 * and the policy manager send routing=0. But if the USB is connected
4453 * back before the standby time, AFE is not closed and opened
4454 * when USB is connected back. So routing to speker will guarantee
4455 * AFE reconfiguration and AFE will be opend once USB is connected again
4456 */
4457 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4458 (val == AUDIO_DEVICE_NONE) &&
4459 !audio_extn_usb_connected(parms)) {
4460 val = AUDIO_DEVICE_OUT_SPEAKER;
4461 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304462 /* To avoid a2dp to sco overlapping / BT device improper state
4463 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304464 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304465 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004466 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004467 if (val &
4468 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304469 //combo usecase just by pass a2dp
4470 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304471 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304472 } else {
4473 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4474 /* update device to a2dp and don't route as BT returned error
4475 * However it is still possible a2dp routing called because
4476 * of current active device disconnection (like wired headset)
4477 */
4478 out->devices = val;
4479 pthread_mutex_unlock(&out->lock);
4480 pthread_mutex_unlock(&adev->lock);
4481 goto error;
4482 }
4483 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304484 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004485
4486 audio_devices_t new_dev = val;
4487
4488 // Workaround: If routing to an non existing usb device, fail gracefully
4489 // The routing request will otherwise block during 10 second
4490 int card;
4491 if (audio_is_usb_out_device(new_dev) &&
4492 (card = get_alive_usb_card(parms)) >= 0) {
4493
4494 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4495 pthread_mutex_unlock(&adev->lock);
4496 pthread_mutex_unlock(&out->lock);
4497 ret = -ENOSYS;
4498 goto routing_fail;
4499 }
4500
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004501 /*
4502 * select_devices() call below switches all the usecases on the same
4503 * backend to the new device. Refer to check_usecases_codec_backend() in
4504 * the select_devices(). But how do we undo this?
4505 *
4506 * For example, music playback is active on headset (deep-buffer usecase)
4507 * and if we go to ringtones and select a ringtone, low-latency usecase
4508 * will be started on headset+speaker. As we can't enable headset+speaker
4509 * and headset devices at the same time, select_devices() switches the music
4510 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4511 * So when the ringtone playback is completed, how do we undo the same?
4512 *
4513 * We are relying on the out_set_parameters() call on deep-buffer output,
4514 * once the ringtone playback is ended.
4515 * NOTE: We should not check if the current devices are same as new devices.
4516 * Because select_devices() must be called to switch back the music
4517 * playback to headset.
4518 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004519 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004520 audio_devices_t new_dev = val;
4521 bool same_dev = out->devices == new_dev;
4522 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004523
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004524 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004525 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004526 if (adev->mode == AUDIO_MODE_IN_CALL) {
4527 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004528 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4529 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4530 audio_extn_usb_set_service_interval(true /*playback*/,
4531 service_interval,
4532 &reconfig);
4533 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4534 }
4535 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004536 }
4537 } else {
4538 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004539 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004540 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004541 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004542
4543 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004544 if (!same_dev) {
4545 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304546 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4547 adev->perf_lock_opts,
4548 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004549 if (adev->adm_on_routing_change)
4550 adev->adm_on_routing_change(adev->adm_data,
4551 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004552 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304553 if (!bypass_a2dp) {
4554 select_devices(adev, out->usecase);
4555 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004556 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4557 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4558 else
4559 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304560 select_devices(adev, out->usecase);
4561 out->devices = new_dev;
4562 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004563
4564 if (!same_dev) {
4565 // on device switch force swap, lower functions will make sure
4566 // to check if swap is allowed or not.
4567 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304568 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004569 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304570 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4571 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004572 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304573 pthread_mutex_lock(&out->compr_mute_lock);
4574 out->a2dp_compress_mute = false;
4575 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4576 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004577 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4578 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304579 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004580 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004581 }
4582
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004583 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004584 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004585
4586 /*handles device and call state changes*/
4587 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004589 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004590
4591 if (out == adev->primary_output) {
4592 pthread_mutex_lock(&adev->lock);
4593 audio_extn_set_parameters(adev, parms);
4594 pthread_mutex_unlock(&adev->lock);
4595 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004596 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004597 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004598 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004599
4600 audio_extn_dts_create_state_notifier_node(out->usecase);
4601 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4602 popcount(out->channel_mask),
4603 out->playback_started);
4604
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004605 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004606 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004607
Surendar Karkaf51b5842018-04-26 11:28:38 +05304608 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4609 sizeof(value));
4610 if (err >= 0) {
4611 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4612 audio_extn_send_dual_mono_mixing_coefficients(out);
4613 }
4614
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304615 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4616 if (err >= 0) {
4617 strlcpy(out->profile, value, sizeof(out->profile));
4618 ALOGV("updating stream profile with value '%s'", out->profile);
4619 lock_output_stream(out);
4620 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4621 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004622 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304623 out->sample_rate, out->bit_width,
4624 out->channel_mask, out->profile,
4625 &out->app_type_cfg);
4626 pthread_mutex_unlock(&out->lock);
4627 }
4628
Alexy Joseph98988832017-01-13 14:56:59 -08004629 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004630 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4631 // and vendor.audio.hal.output.suspend.supported is set to true
4632 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004633 //check suspend parameter only for low latency and if the property
4634 //is enabled
4635 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4636 ALOGI("%s: got suspend_playback %s", __func__, value);
4637 lock_output_stream(out);
4638 if (!strncmp(value, "false", 5)) {
4639 //suspend_playback=false is supposed to set QOS value back to 75%
4640 //the mixer control sent with value Enable will achieve that
4641 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4642 } else if (!strncmp (value, "true", 4)) {
4643 //suspend_playback=true is supposed to remove QOS value
4644 //resetting the mixer control will set the default value
4645 //for the mixer control which is Disable and this removes the QOS vote
4646 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4647 } else {
4648 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4649 " got %s", __func__, value);
4650 ret = -1;
4651 }
4652
4653 if (ret != 0) {
4654 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4655 __func__, out->pm_qos_mixer_path, ret);
4656 }
4657
4658 pthread_mutex_unlock(&out->lock);
4659 }
4660 }
4661 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004662 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304663error:
Eric Laurent994a6932013-07-17 11:51:42 -07004664 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004665 return ret;
4666}
4667
Paul McLeana50b7332018-12-17 08:24:21 -07004668static int in_set_microphone_direction(const struct audio_stream_in *stream,
4669 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004670 struct stream_in *in = (struct stream_in *)stream;
4671
4672 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4673
4674 in->direction = dir;
4675
4676 if (in->standby)
4677 return 0;
4678
4679 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004680}
4681
4682static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004683 struct stream_in *in = (struct stream_in *)stream;
4684
4685 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4686
4687 if (zoom > 1.0 || zoom < -1.0)
4688 return -EINVAL;
4689
4690 in->zoom = zoom;
4691
4692 if (in->standby)
4693 return 0;
4694
4695 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004696}
4697
4698
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004699static bool stream_get_parameter_channels(struct str_parms *query,
4700 struct str_parms *reply,
4701 audio_channel_mask_t *supported_channel_masks) {
4702 int ret = -1;
4703 char value[512];
4704 bool first = true;
4705 size_t i, j;
4706
4707 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4708 ret = 0;
4709 value[0] = '\0';
4710 i = 0;
4711 while (supported_channel_masks[i] != 0) {
4712 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4713 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4714 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304715 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004716
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304717 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004718 first = false;
4719 break;
4720 }
4721 }
4722 i++;
4723 }
4724 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4725 }
4726 return ret == 0;
4727}
4728
4729static bool stream_get_parameter_formats(struct str_parms *query,
4730 struct str_parms *reply,
4731 audio_format_t *supported_formats) {
4732 int ret = -1;
4733 char value[256];
4734 size_t i, j;
4735 bool first = true;
4736
4737 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4738 ret = 0;
4739 value[0] = '\0';
4740 i = 0;
4741 while (supported_formats[i] != 0) {
4742 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4743 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4744 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304745 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004746 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304747 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004748 first = false;
4749 break;
4750 }
4751 }
4752 i++;
4753 }
4754 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4755 }
4756 return ret == 0;
4757}
4758
4759static bool stream_get_parameter_rates(struct str_parms *query,
4760 struct str_parms *reply,
4761 uint32_t *supported_sample_rates) {
4762
4763 int i;
4764 char value[256];
4765 int ret = -1;
4766 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4767 ret = 0;
4768 value[0] = '\0';
4769 i=0;
4770 int cursor = 0;
4771 while (supported_sample_rates[i]) {
4772 int avail = sizeof(value) - cursor;
4773 ret = snprintf(value + cursor, avail, "%s%d",
4774 cursor > 0 ? "|" : "",
4775 supported_sample_rates[i]);
4776 if (ret < 0 || ret >= avail) {
4777 // if cursor is at the last element of the array
4778 // overwrite with \0 is duplicate work as
4779 // snprintf already put a \0 in place.
4780 // else
4781 // we had space to write the '|' at value[cursor]
4782 // (which will be overwritten) or no space to fill
4783 // the first element (=> cursor == 0)
4784 value[cursor] = '\0';
4785 break;
4786 }
4787 cursor += ret;
4788 ++i;
4789 }
4790 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4791 value);
4792 }
4793 return ret >= 0;
4794}
4795
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004796static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4797{
4798 struct stream_out *out = (struct stream_out *)stream;
4799 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004800 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004801 char value[256];
4802 struct str_parms *reply = str_parms_create();
4803 size_t i, j;
4804 int ret;
4805 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004806
4807 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004808 if (reply) {
4809 str_parms_destroy(reply);
4810 }
4811 if (query) {
4812 str_parms_destroy(query);
4813 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004814 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4815 return NULL;
4816 }
4817
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004818 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004819 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4820 if (ret >= 0) {
4821 value[0] = '\0';
4822 i = 0;
4823 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004824 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4825 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004826 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004827 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004828 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004829 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004830 first = false;
4831 break;
4832 }
4833 }
4834 i++;
4835 }
4836 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4837 str = str_parms_to_str(reply);
4838 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004839 voice_extn_out_get_parameters(out, query, reply);
4840 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004841 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004842
Alexy Joseph62142aa2015-11-16 15:10:34 -08004843
4844 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4845 if (ret >= 0) {
4846 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304847 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4848 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004849 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304850 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004851 } else {
4852 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304853 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004854 }
4855 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004856 if (str)
4857 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004858 str = str_parms_to_str(reply);
4859 }
4860
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004861 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4862 if (ret >= 0) {
4863 value[0] = '\0';
4864 i = 0;
4865 first = true;
4866 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004867 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4868 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004869 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004870 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004871 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004872 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004873 first = false;
4874 break;
4875 }
4876 }
4877 i++;
4878 }
4879 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004880 if (str)
4881 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004882 str = str_parms_to_str(reply);
4883 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004884
4885 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4886 if (ret >= 0) {
4887 value[0] = '\0';
4888 i = 0;
4889 first = true;
4890 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004891 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4892 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004893 if (!first) {
4894 strlcat(value, "|", sizeof(value));
4895 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004896 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004897 first = false;
4898 break;
4899 }
4900 }
4901 i++;
4902 }
4903 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4904 if (str)
4905 free(str);
4906 str = str_parms_to_str(reply);
4907 }
4908
Alexy Joseph98988832017-01-13 14:56:59 -08004909 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4910 //only low latency track supports suspend_resume
4911 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004912 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004913 if (str)
4914 free(str);
4915 str = str_parms_to_str(reply);
4916 }
4917
4918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004919 str_parms_destroy(query);
4920 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004921 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004922 return str;
4923}
4924
4925static uint32_t out_get_latency(const struct audio_stream_out *stream)
4926{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004927 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004928 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004929 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004930
Alexy Josephaa54c872014-12-03 02:46:47 -08004931 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304932 lock_output_stream(out);
4933 latency = audio_extn_utils_compress_get_dsp_latency(out);
4934 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004935 } else if ((out->realtime) ||
4936 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004937 // since the buffer won't be filled up faster than realtime,
4938 // return a smaller number
4939 if (out->config.rate)
4940 period_ms = (out->af_period_multiplier * out->config.period_size *
4941 1000) / (out->config.rate);
4942 else
4943 period_ms = 0;
4944 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004945 } else {
4946 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004947 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004948 }
4949
yidongh0515e042017-07-06 15:00:34 +08004950 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004951 latency += audio_extn_a2dp_get_encoder_latency();
4952
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304953 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004954 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004955}
4956
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304957static float AmpToDb(float amplification)
4958{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304959 float db = DSD_VOLUME_MIN_DB;
4960 if (amplification > 0) {
4961 db = 20 * log10(amplification);
4962 if(db < DSD_VOLUME_MIN_DB)
4963 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304964 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304965 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304966}
4967
Arun Mirpuri5d170872019-03-26 13:21:31 -07004968static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4969 float right)
4970{
4971 struct stream_out *out = (struct stream_out *)stream;
4972 long volume = 0;
4973 char mixer_ctl_name[128] = "";
4974 struct audio_device *adev = out->dev;
4975 struct mixer_ctl *ctl = NULL;
4976 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4977 PCM_PLAYBACK);
4978
4979 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4980 "Playback %d Volume", pcm_device_id);
4981 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4982 if (!ctl) {
4983 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4984 __func__, mixer_ctl_name);
4985 return -EINVAL;
4986 }
4987 if (left != right)
4988 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4989 __func__, left, right);
4990 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4991 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4992 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4993 __func__, mixer_ctl_name, volume);
4994 return -EINVAL;
4995 }
4996 return 0;
4997}
4998
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304999static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5000 float right)
5001{
5002 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305003 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305004 char mixer_ctl_name[128];
5005 struct audio_device *adev = out->dev;
5006 struct mixer_ctl *ctl;
5007 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5008 PCM_PLAYBACK);
5009
5010 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5011 "Compress Playback %d Volume", pcm_device_id);
5012 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5013 if (!ctl) {
5014 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5015 __func__, mixer_ctl_name);
5016 return -EINVAL;
5017 }
5018 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5019 __func__, mixer_ctl_name, left, right);
5020 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5021 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5022 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5023
5024 return 0;
5025}
5026
Zhou Song2b8f28f2017-09-11 10:51:38 +08005027static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5028 float right)
5029{
5030 struct stream_out *out = (struct stream_out *)stream;
5031 char mixer_ctl_name[] = "App Type Gain";
5032 struct audio_device *adev = out->dev;
5033 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305034 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005035
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005036 if (!is_valid_volume(left, right)) {
5037 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5038 __func__, left, right);
5039 return -EINVAL;
5040 }
5041
Zhou Song2b8f28f2017-09-11 10:51:38 +08005042 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5043 if (!ctl) {
5044 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5045 __func__, mixer_ctl_name);
5046 return -EINVAL;
5047 }
5048
5049 set_values[0] = 0; //0: Rx Session 1:Tx Session
5050 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305051 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5052 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005053
5054 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5055 return 0;
5056}
5057
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305058static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5059 float right)
5060{
5061 struct stream_out *out = (struct stream_out *)stream;
5062 /* Volume control for pcm playback */
5063 if (left != right) {
5064 return -EINVAL;
5065 } else {
5066 char mixer_ctl_name[128];
5067 struct audio_device *adev = out->dev;
5068 struct mixer_ctl *ctl;
5069 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5070 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5071 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5072 if (!ctl) {
5073 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5074 return -EINVAL;
5075 }
5076
5077 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5078 int ret = mixer_ctl_set_value(ctl, 0, volume);
5079 if (ret < 0) {
5080 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5081 return -EINVAL;
5082 }
5083
5084 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5085
5086 return 0;
5087 }
5088}
5089
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005090static int out_set_volume(struct audio_stream_out *stream, float left,
5091 float right)
5092{
Eric Laurenta9024de2013-04-04 09:19:12 -07005093 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005094 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305095 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005096
Arun Mirpuri5d170872019-03-26 13:21:31 -07005097 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005098 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5099 /* only take left channel into account: the API is for stereo anyway */
5100 out->muted = (left == 0.0f);
5101 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005102 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305103 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005104 /*
5105 * Set mute or umute on HDMI passthrough stream.
5106 * Only take left channel into account.
5107 * Mute is 0 and unmute 1
5108 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305109 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305110 } else if (out->format == AUDIO_FORMAT_DSD){
5111 char mixer_ctl_name[128] = "DSD Volume";
5112 struct audio_device *adev = out->dev;
5113 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5114
5115 if (!ctl) {
5116 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5117 __func__, mixer_ctl_name);
5118 return -EINVAL;
5119 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305120 volume[0] = (long)(AmpToDb(left));
5121 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305122 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5123 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005124 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305125 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005126 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305127 if (!out->a2dp_compress_mute)
5128 ret = out_set_compr_volume(stream, left, right);
5129 out->volume_l = left;
5130 out->volume_r = right;
5131 pthread_mutex_unlock(&out->compr_mute_lock);
5132 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005133 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005134 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005135 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5136 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5137 if (!out->standby) {
5138 audio_extn_utils_send_app_type_gain(out->dev,
5139 out->app_type_cfg.app_type,
5140 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005141 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005142 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005143 out->volume_l = left;
5144 out->volume_r = right;
5145 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005146 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5147 ALOGV("%s: MMAP set volume called", __func__);
5148 if (!out->standby)
5149 ret = out_set_mmap_volume(stream, left, right);
5150 out->volume_l = left;
5151 out->volume_r = right;
5152 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305153 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305154 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5155 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305156 /* Volume control for pcm playback */
5157 if (!out->standby)
5158 ret = out_set_pcm_volume(stream, left, right);
5159 else
5160 out->apply_volume = true;
5161
5162 out->volume_l = left;
5163 out->volume_r = right;
5164 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005165 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5166 ALOGV("%s: bus device set volume called", __func__);
5167 if (!out->standby)
5168 ret = out_set_pcm_volume(stream, left, right);
5169 out->volume_l = left;
5170 out->volume_r = right;
5171 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005172 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005173
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005174 return -ENOSYS;
5175}
5176
Zhou Songc9672822017-08-16 16:01:39 +08005177static void update_frames_written(struct stream_out *out, size_t bytes)
5178{
5179 size_t bpf = 0;
5180
5181 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5182 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5183 bpf = 1;
5184 else if (!is_offload_usecase(out->usecase))
5185 bpf = audio_bytes_per_sample(out->format) *
5186 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005187
5188 pthread_mutex_lock(&out->position_query_lock);
5189 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005190 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005191 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5192 }
5193 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005194}
5195
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005196int split_and_write_audio_haptic_data(struct stream_out *out,
5197 const void *buffer, size_t bytes_to_write)
5198{
5199 struct audio_device *adev = out->dev;
5200
5201 int ret = 0;
5202 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5203 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5204 size_t frame_size = channel_count * bytes_per_sample;
5205 size_t frame_count = bytes_to_write / frame_size;
5206
5207 bool force_haptic_path =
5208 property_get_bool("vendor.audio.test_haptic", false);
5209
5210 // extract Haptics data from Audio buffer
5211 bool alloc_haptic_buffer = false;
5212 int haptic_channel_count = adev->haptics_config.channels;
5213 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5214 size_t audio_frame_size = frame_size - haptic_frame_size;
5215 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5216
5217 if (adev->haptic_buffer == NULL) {
5218 alloc_haptic_buffer = true;
5219 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5220 free(adev->haptic_buffer);
5221 adev->haptic_buffer_size = 0;
5222 alloc_haptic_buffer = true;
5223 }
5224
5225 if (alloc_haptic_buffer) {
5226 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005227 if(adev->haptic_buffer == NULL) {
5228 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5229 return -ENOMEM;
5230 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005231 adev->haptic_buffer_size = total_haptic_buffer_size;
5232 }
5233
5234 size_t src_index = 0, aud_index = 0, hap_index = 0;
5235 uint8_t *audio_buffer = (uint8_t *)buffer;
5236 uint8_t *haptic_buffer = adev->haptic_buffer;
5237
5238 // This is required for testing only. This works for stereo data only.
5239 // One channel is fed to audio stream and other to haptic stream for testing.
5240 if (force_haptic_path)
5241 audio_frame_size = haptic_frame_size = bytes_per_sample;
5242
5243 for (size_t i = 0; i < frame_count; i++) {
5244 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5245 audio_frame_size);
5246 aud_index += audio_frame_size;
5247 src_index += audio_frame_size;
5248
5249 if (adev->haptic_pcm)
5250 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5251 haptic_frame_size);
5252 hap_index += haptic_frame_size;
5253 src_index += haptic_frame_size;
5254
5255 // This is required for testing only.
5256 // Discard haptic channel data.
5257 if (force_haptic_path)
5258 src_index += haptic_frame_size;
5259 }
5260
5261 // write to audio pipeline
5262 ret = pcm_write(out->pcm, (void *)audio_buffer,
5263 frame_count * audio_frame_size);
5264
5265 // write to haptics pipeline
5266 if (adev->haptic_pcm)
5267 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5268 frame_count * haptic_frame_size);
5269
5270 return ret;
5271}
5272
Aalique Grahame22e49102018-12-18 14:23:57 -08005273#ifdef NO_AUDIO_OUT
5274static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5275 const void *buffer __unused, size_t bytes)
5276{
5277 struct stream_out *out = (struct stream_out *)stream;
5278
5279 /* No Output device supported other than BT for playback.
5280 * Sleep for the amount of buffer duration
5281 */
5282 lock_output_stream(out);
5283 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5284 (const struct audio_stream_out *)&out->stream) /
5285 out_get_sample_rate(&out->stream.common));
5286 pthread_mutex_unlock(&out->lock);
5287 return bytes;
5288}
5289#endif
5290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005291static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5292 size_t bytes)
5293{
5294 struct stream_out *out = (struct stream_out *)stream;
5295 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005296 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305297 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005298 const size_t frame_size = audio_stream_out_frame_size(stream);
5299 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305300 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005301
Haynes Mathew George380745d2017-10-04 15:27:45 -07005302 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005303 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305304
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305305 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005306
Dhananjay Kumarac341582017-02-23 23:42:25 +05305307 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305308 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305309 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5310 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005311 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305312 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305313 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305314 ALOGD(" %s: sound card is not active/SSR state", __func__);
5315 ret= -EIO;
5316 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305317 }
5318 }
5319
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305320 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305321 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305322 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305323 goto exit;
5324 }
5325
Haynes Mathew George16081042017-05-31 17:16:49 -07005326 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5327 ret = -EINVAL;
5328 goto exit;
5329 }
5330
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305331 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5332 !out->is_iec61937_info_available) {
5333
5334 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5335 out->is_iec61937_info_available = true;
5336 } else if (audio_extn_passthru_is_enabled()) {
5337 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305338 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305339
5340 if((out->format == AUDIO_FORMAT_DTS) ||
5341 (out->format == AUDIO_FORMAT_DTS_HD)) {
5342 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5343 buffer, bytes);
5344 if (ret) {
5345 if (ret != -ENOSYS) {
5346 out->is_iec61937_info_available = false;
5347 ALOGD("iec61937 transmission info not yet updated retry");
5348 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305349 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305350 /* if stream has started and after that there is
5351 * stream config change (iec transmission config)
5352 * then trigger select_device to update backend configuration.
5353 */
5354 out->stream_config_changed = true;
5355 pthread_mutex_lock(&adev->lock);
5356 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305357 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005358 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305359 ret = -EINVAL;
5360 goto exit;
5361 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305362 pthread_mutex_unlock(&adev->lock);
5363 out->stream_config_changed = false;
5364 out->is_iec61937_info_available = true;
5365 }
5366 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305367
Garmond Leung317cbf12017-09-13 16:20:50 -07005368 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305369 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5370 (out->is_iec61937_info_available == true)) {
5371 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5372 ret = -EINVAL;
5373 goto exit;
5374 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305375 }
5376 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305377
5378 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005379 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005380 if (!(out->devices &
5381 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305382 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305383 ret = -EIO;
5384 goto exit;
5385 }
5386 }
5387 }
5388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005389 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005390 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005391 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005392 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5393 ret = voice_extn_compress_voip_start_output_stream(out);
5394 else
5395 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005396 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005397 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005398 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005399 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005400 goto exit;
5401 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305402 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005403 if (last_known_cal_step != -1) {
5404 ALOGD("%s: retry previous failed cal level set", __func__);
5405 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305406 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005407 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305408
5409 if ((out->is_iec61937_info_available == true) &&
5410 (audio_extn_passthru_is_passthrough_stream(out))&&
5411 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5412 ret = -EINVAL;
5413 goto exit;
5414 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305415 if (out->set_dual_mono)
5416 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005417 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005418
Ashish Jain81eb2a82015-05-13 10:52:34 +05305419 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005420 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305421 adev->is_channel_status_set = true;
5422 }
5423
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305424 if ((adev->use_old_pspd_mix_ctrl == true) &&
5425 (out->pspd_coeff_sent == false)) {
5426 /*
5427 * Need to resend pspd coefficients after stream started for
5428 * older kernel version as it does not save the coefficients
5429 * and also stream has to be started for coeff to apply.
5430 */
5431 usecase = get_usecase_from_list(adev, out->usecase);
5432 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305433 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305434 out->pspd_coeff_sent = true;
5435 }
5436 }
5437
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005438 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005439 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005440 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005441 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005442 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5443 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305444 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5445 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005446 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305447 out->send_next_track_params = false;
5448 out->is_compr_metadata_avail = false;
5449 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005450 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305451 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305452 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005453
Ashish Jain83a6cc22016-06-28 14:34:17 +05305454 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305455 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305456 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305457 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005458 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305459 return -EINVAL;
5460 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305461 audio_format_t dst_format = out->hal_op_format;
5462 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305463
Dieter Luecking5d57def2018-09-07 14:23:37 +02005464 /* prevent division-by-zero */
5465 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5466 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5467 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5468 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305469 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005470 ATRACE_END();
5471 return -EINVAL;
5472 }
5473
Ashish Jainf1eaa582016-05-23 20:54:24 +05305474 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5475 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5476
Ashish Jain83a6cc22016-06-28 14:34:17 +05305477 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305478 dst_format,
5479 buffer,
5480 src_format,
5481 frames);
5482
Ashish Jain83a6cc22016-06-28 14:34:17 +05305483 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305484 bytes_to_write);
5485
5486 /*Convert written bytes in audio flinger format*/
5487 if (ret > 0)
5488 ret = ((ret * format_to_bitwidth_table[out->format]) /
5489 format_to_bitwidth_table[dst_format]);
5490 }
5491 } else
5492 ret = compress_write(out->compr, buffer, bytes);
5493
Zhou Songc9672822017-08-16 16:01:39 +08005494 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5495 update_frames_written(out, bytes);
5496
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305497 if (ret < 0)
5498 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005499 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305500 /*msg to cb thread only if non blocking write is enabled*/
5501 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305502 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005503 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305504 } else if (-ENETRESET == ret) {
5505 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305506 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305507 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305508 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005509 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305510 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005511 }
Ashish Jain5106d362016-05-11 19:23:33 +05305512
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305513 /* Call compr start only when non-zero bytes of data is there to be rendered */
5514 if (!out->playback_started && ret > 0) {
5515 int status = compress_start(out->compr);
5516 if (status < 0) {
5517 ret = status;
5518 ALOGE("%s: compr start failed with err %d", __func__, errno);
5519 goto exit;
5520 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005521 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005522 out->playback_started = 1;
5523 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005524
5525 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5526 popcount(out->channel_mask),
5527 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005528 }
5529 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005530 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005531 return ret;
5532 } else {
5533 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005534 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005535 if (out->muted)
5536 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005537 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5538 __func__, frames, frame_size, bytes_to_write);
5539
Aalique Grahame22e49102018-12-18 14:23:57 -08005540 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005541 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5542 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5543 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005544 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5545 int16_t *src = (int16_t *)buffer;
5546 int16_t *dst = (int16_t *)buffer;
5547
5548 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5549 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005550 "out_write called for %s use case with wrong properties",
5551 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005552
5553 /*
5554 * FIXME: this can be removed once audio flinger mixer supports
5555 * mono output
5556 */
5557
5558 /*
5559 * Code below goes over each frame in the buffer and adds both
5560 * L and R samples and then divides by 2 to convert to mono
5561 */
5562 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5563 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5564 }
5565 bytes_to_write /= 2;
5566 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005567
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305568 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005569
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005570 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005571
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005572 if (out->config.rate)
5573 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5574 out->config.rate;
5575
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005576 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005577 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5578
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005579 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005580 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005581 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305582 out->convert_buffer != NULL) {
5583
5584 memcpy_by_audio_format(out->convert_buffer,
5585 out->hal_op_format,
5586 buffer,
5587 out->hal_ip_format,
5588 out->config.period_size * out->config.channels);
5589
5590 ret = pcm_write(out->pcm, out->convert_buffer,
5591 (out->config.period_size *
5592 out->config.channels *
5593 format_to_bitwidth_table[out->hal_op_format]));
5594 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305595 /*
5596 * To avoid underrun in DSP when the application is not pumping
5597 * data at required rate, check for the no. of bytes and ignore
5598 * pcm_write if it is less than actual buffer size.
5599 * It is a work around to a change in compress VOIP driver.
5600 */
5601 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5602 bytes < (out->config.period_size * out->config.channels *
5603 audio_bytes_per_sample(out->format))) {
5604 size_t voip_buf_size =
5605 out->config.period_size * out->config.channels *
5606 audio_bytes_per_sample(out->format);
5607 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5608 __func__, bytes, voip_buf_size);
5609 usleep(((uint64_t)voip_buf_size - bytes) *
5610 1000000 / audio_stream_out_frame_size(stream) /
5611 out_get_sample_rate(&out->stream.common));
5612 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005613 } else {
5614 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5615 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5616 else
5617 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5618 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305619 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005620
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005621 release_out_focus(out);
5622
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305623 if (ret < 0)
5624 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005625 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305626 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005627 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005628 }
5629
5630exit:
Zhou Songc9672822017-08-16 16:01:39 +08005631 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305632 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305633 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305634 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005635 pthread_mutex_unlock(&out->lock);
5636
5637 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005638 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005639 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305640 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305641 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305642 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305643 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305644 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305645 out->standby = true;
5646 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305647 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005648 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5649 /* prevent division-by-zero */
5650 uint32_t stream_size = audio_stream_out_frame_size(stream);
5651 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005652
Dieter Luecking5d57def2018-09-07 14:23:37 +02005653 if ((stream_size == 0) || (srate == 0)) {
5654 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5655 ATRACE_END();
5656 return -EINVAL;
5657 }
5658 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5659 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005660 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305661 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005662 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005663 return ret;
5664 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005665 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005666 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005667 return bytes;
5668}
5669
5670static int out_get_render_position(const struct audio_stream_out *stream,
5671 uint32_t *dsp_frames)
5672{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005673 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005674
5675 if (dsp_frames == NULL)
5676 return -EINVAL;
5677
5678 *dsp_frames = 0;
5679 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005680 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305681
5682 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5683 * this operation and adev_close_output_stream(where out gets reset).
5684 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305685 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005686 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305687 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005688 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305689 return 0;
5690 }
5691
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005692 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305693 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305694 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005695 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305696 if (ret < 0)
5697 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005698 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305699 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005700 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305701 if (-ENETRESET == ret) {
5702 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305703 out->card_status = CARD_STATUS_OFFLINE;
5704 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305705 } else if(ret < 0) {
5706 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305707 ret = -EINVAL;
5708 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305709 /*
5710 * Handle corner case where compress session is closed during SSR
5711 * and timestamp is queried
5712 */
5713 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305714 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305715 } else if (out->prev_card_status_offline) {
5716 ALOGE("ERROR: previously sound card was offline,return error");
5717 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305718 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305719 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005720 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305721 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305722 pthread_mutex_unlock(&out->lock);
5723 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005724 } else if (audio_is_linear_pcm(out->format)) {
5725 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005726 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005727 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005728 } else
5729 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005730}
5731
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005732static int out_add_audio_effect(const struct audio_stream *stream __unused,
5733 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005734{
5735 return 0;
5736}
5737
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005738static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5739 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005740{
5741 return 0;
5742}
5743
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005744static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5745 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005746{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305747 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005748}
5749
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005750static int out_get_presentation_position(const struct audio_stream_out *stream,
5751 uint64_t *frames, struct timespec *timestamp)
5752{
5753 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305754 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005755 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005756
Ashish Jain5106d362016-05-11 19:23:33 +05305757 /* below piece of code is not guarded against any lock because audioFliner serializes
5758 * this operation and adev_close_output_stream( where out gets reset).
5759 */
5760 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305761 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005762 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305763 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5764 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5765 return 0;
5766 }
5767
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005768 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005769
Ashish Jain5106d362016-05-11 19:23:33 +05305770 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5771 ret = compress_get_tstamp(out->compr, &dsp_frames,
5772 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005773 // Adjustment accounts for A2dp encoder latency with offload usecases
5774 // Note: Encoder latency is returned in ms.
5775 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5776 unsigned long offset =
5777 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5778 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5779 }
Ashish Jain5106d362016-05-11 19:23:33 +05305780 ALOGVV("%s rendered frames %ld sample_rate %d",
5781 __func__, dsp_frames, out->sample_rate);
5782 *frames = dsp_frames;
5783 if (ret < 0)
5784 ret = -errno;
5785 if (-ENETRESET == ret) {
5786 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305787 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305788 ret = -EINVAL;
5789 } else
5790 ret = 0;
5791 /* this is the best we can do */
5792 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005793 } else {
5794 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005795 unsigned int avail;
5796 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5797 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5798 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5799 // This adjustment accounts for buffering after app processor.
5800 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005801 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005802 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005803
Weiyin Jiangd4633762018-03-16 12:05:03 +08005804 // Adjustment accounts for A2dp encoder latency with non offload usecases
5805 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5806 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5807 signed_frames -=
5808 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5809 }
5810
5811 // It would be unusual for this value to be negative, but check just in case ...
5812 if (signed_frames >= 0) {
5813 *frames = signed_frames;
5814 ret = 0;
5815 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005816 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305817 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305818 *frames = out->written;
5819 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305820 if (is_offload_usecase(out->usecase))
5821 ret = -EINVAL;
5822 else
5823 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005824 }
5825 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005826 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005827 return ret;
5828}
5829
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005830static int out_set_callback(struct audio_stream_out *stream,
5831 stream_callback_t callback, void *cookie)
5832{
5833 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005834 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005835
5836 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005837 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005838 out->client_callback = callback;
5839 out->client_cookie = cookie;
5840 if (out->adsp_hdlr_stream_handle) {
5841 ret = audio_extn_adsp_hdlr_stream_set_callback(
5842 out->adsp_hdlr_stream_handle,
5843 callback,
5844 cookie);
5845 if (ret)
5846 ALOGW("%s:adsp hdlr callback registration failed %d",
5847 __func__, ret);
5848 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005849 pthread_mutex_unlock(&out->lock);
5850 return 0;
5851}
5852
5853static int out_pause(struct audio_stream_out* stream)
5854{
5855 struct stream_out *out = (struct stream_out *)stream;
5856 int status = -ENOSYS;
5857 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005858 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005859 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005860 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005861 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305862 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305863 status = compress_pause(out->compr);
5864
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005865 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005866
Mingming Yin21854652016-04-13 11:54:02 -07005867 if (audio_extn_passthru_is_active()) {
5868 ALOGV("offload use case, pause passthru");
5869 audio_extn_passthru_on_pause(out);
5870 }
5871
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305872 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005873 audio_extn_dts_notify_playback_state(out->usecase, 0,
5874 out->sample_rate, popcount(out->channel_mask),
5875 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005876 }
5877 pthread_mutex_unlock(&out->lock);
5878 }
5879 return status;
5880}
5881
5882static int out_resume(struct audio_stream_out* stream)
5883{
5884 struct stream_out *out = (struct stream_out *)stream;
5885 int status = -ENOSYS;
5886 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005887 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005888 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005889 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005890 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005891 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305892 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305893 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005894 }
5895 if (!status) {
5896 out->offload_state = OFFLOAD_STATE_PLAYING;
5897 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305898 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005899 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5900 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005901 }
5902 pthread_mutex_unlock(&out->lock);
5903 }
5904 return status;
5905}
5906
5907static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5908{
5909 struct stream_out *out = (struct stream_out *)stream;
5910 int status = -ENOSYS;
5911 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005912 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005913 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005914 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5915 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5916 else
5917 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5918 pthread_mutex_unlock(&out->lock);
5919 }
5920 return status;
5921}
5922
5923static int out_flush(struct audio_stream_out* stream)
5924{
5925 struct stream_out *out = (struct stream_out *)stream;
5926 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005927 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005928 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005929 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005930 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5931 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005932 } else {
5933 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5934 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005935 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005936 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005937 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005938 return 0;
5939 }
5940 return -ENOSYS;
5941}
5942
Haynes Mathew George16081042017-05-31 17:16:49 -07005943static int out_stop(const struct audio_stream_out* stream)
5944{
5945 struct stream_out *out = (struct stream_out *)stream;
5946 struct audio_device *adev = out->dev;
5947 int ret = -ENOSYS;
5948
5949 ALOGV("%s", __func__);
5950 pthread_mutex_lock(&adev->lock);
5951 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5952 out->playback_started && out->pcm != NULL) {
5953 pcm_stop(out->pcm);
5954 ret = stop_output_stream(out);
5955 out->playback_started = false;
5956 }
5957 pthread_mutex_unlock(&adev->lock);
5958 return ret;
5959}
5960
5961static int out_start(const struct audio_stream_out* stream)
5962{
5963 struct stream_out *out = (struct stream_out *)stream;
5964 struct audio_device *adev = out->dev;
5965 int ret = -ENOSYS;
5966
5967 ALOGV("%s", __func__);
5968 pthread_mutex_lock(&adev->lock);
5969 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5970 !out->playback_started && out->pcm != NULL) {
5971 ret = start_output_stream(out);
5972 if (ret == 0) {
5973 out->playback_started = true;
5974 }
5975 }
5976 pthread_mutex_unlock(&adev->lock);
5977 return ret;
5978}
5979
5980/*
5981 * Modify config->period_count based on min_size_frames
5982 */
5983static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5984{
5985 int periodCountRequested = (min_size_frames + config->period_size - 1)
5986 / config->period_size;
5987 int periodCount = MMAP_PERIOD_COUNT_MIN;
5988
5989 ALOGV("%s original config.period_size = %d config.period_count = %d",
5990 __func__, config->period_size, config->period_count);
5991
5992 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5993 periodCount *= 2;
5994 }
5995 config->period_count = periodCount;
5996
5997 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5998}
5999
Phil Burkfe17efd2019-03-25 10:23:35 -07006000// Read offset for the positional timestamp from a persistent vendor property.
6001// This is to workaround apparent inaccuracies in the timing information that
6002// is used by the AAudio timing model. The inaccuracies can cause glitches.
6003static int64_t get_mmap_out_time_offset() {
6004 const int32_t kDefaultOffsetMicros = 0;
6005 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006006 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006007 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6008 return mmap_time_offset_micros * (int64_t)1000;
6009}
6010
Haynes Mathew George16081042017-05-31 17:16:49 -07006011static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6012 int32_t min_size_frames,
6013 struct audio_mmap_buffer_info *info)
6014{
6015 struct stream_out *out = (struct stream_out *)stream;
6016 struct audio_device *adev = out->dev;
6017 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006018 unsigned int offset1 = 0;
6019 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006020 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006021 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006022 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006023
Arun Mirpuri5d170872019-03-26 13:21:31 -07006024 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306025 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006026 pthread_mutex_lock(&adev->lock);
6027
Sharad Sanglec6f32552018-05-04 16:15:38 +05306028 if (CARD_STATUS_OFFLINE == out->card_status ||
6029 CARD_STATUS_OFFLINE == adev->card_status) {
6030 ALOGW("out->card_status or adev->card_status offline, try again");
6031 ret = -EIO;
6032 goto exit;
6033 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006034 if (info == NULL || min_size_frames == 0) {
6035 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6036 ret = -EINVAL;
6037 goto exit;
6038 }
6039 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6040 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6041 ret = -ENOSYS;
6042 goto exit;
6043 }
6044 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6045 if (out->pcm_device_id < 0) {
6046 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6047 __func__, out->pcm_device_id, out->usecase);
6048 ret = -EINVAL;
6049 goto exit;
6050 }
6051
6052 adjust_mmap_period_count(&out->config, min_size_frames);
6053
Arun Mirpuri5d170872019-03-26 13:21:31 -07006054 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006055 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6056 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6057 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306058 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306059 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6060 out->card_status = CARD_STATUS_OFFLINE;
6061 adev->card_status = CARD_STATUS_OFFLINE;
6062 ret = -EIO;
6063 goto exit;
6064 }
6065
Haynes Mathew George16081042017-05-31 17:16:49 -07006066 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6067 step = "open";
6068 ret = -ENODEV;
6069 goto exit;
6070 }
6071 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6072 if (ret < 0) {
6073 step = "begin";
6074 goto exit;
6075 }
6076 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006077 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006078 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006079 ret = platform_get_mmap_data_fd(adev->platform,
6080 out->pcm_device_id, 0 /*playback*/,
6081 &info->shared_memory_fd,
6082 &mmap_size);
6083 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006084 // Fall back to non exclusive mode
6085 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6086 } else {
6087 if (mmap_size < buffer_size) {
6088 step = "mmap";
6089 goto exit;
6090 }
6091 // FIXME: indicate exclusive mode support by returning a negative buffer size
6092 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006093 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006094 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006095 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006096
6097 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6098 if (ret < 0) {
6099 step = "commit";
6100 goto exit;
6101 }
6102
Phil Burkfe17efd2019-03-25 10:23:35 -07006103 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6104
Haynes Mathew George16081042017-05-31 17:16:49 -07006105 out->standby = false;
6106 ret = 0;
6107
Arun Mirpuri5d170872019-03-26 13:21:31 -07006108 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006109 __func__, info->shared_memory_address, info->buffer_size_frames);
6110
6111exit:
6112 if (ret != 0) {
6113 if (out->pcm == NULL) {
6114 ALOGE("%s: %s - %d", __func__, step, ret);
6115 } else {
6116 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6117 pcm_close(out->pcm);
6118 out->pcm = NULL;
6119 }
6120 }
6121 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306122 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006123 return ret;
6124}
6125
6126static int out_get_mmap_position(const struct audio_stream_out *stream,
6127 struct audio_mmap_position *position)
6128{
6129 struct stream_out *out = (struct stream_out *)stream;
6130 ALOGVV("%s", __func__);
6131 if (position == NULL) {
6132 return -EINVAL;
6133 }
6134 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006135 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006136 return -ENOSYS;
6137 }
6138 if (out->pcm == NULL) {
6139 return -ENOSYS;
6140 }
6141
6142 struct timespec ts = { 0, 0 };
6143 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6144 if (ret < 0) {
6145 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6146 return ret;
6147 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006148 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6149 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006150 return 0;
6151}
6152
6153
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006154/** audio_stream_in implementation **/
6155static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6156{
6157 struct stream_in *in = (struct stream_in *)stream;
6158
6159 return in->config.rate;
6160}
6161
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006162static int in_set_sample_rate(struct audio_stream *stream __unused,
6163 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006164{
6165 return -ENOSYS;
6166}
6167
6168static size_t in_get_buffer_size(const struct audio_stream *stream)
6169{
6170 struct stream_in *in = (struct stream_in *)stream;
6171
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006172 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6173 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006174 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6175 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306176 else if(audio_extn_cin_attached_usecase(in->usecase))
6177 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006178
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006179 return in->config.period_size * in->af_period_multiplier *
6180 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006181}
6182
6183static uint32_t in_get_channels(const struct audio_stream *stream)
6184{
6185 struct stream_in *in = (struct stream_in *)stream;
6186
6187 return in->channel_mask;
6188}
6189
6190static audio_format_t in_get_format(const struct audio_stream *stream)
6191{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006192 struct stream_in *in = (struct stream_in *)stream;
6193
6194 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006195}
6196
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006197static int in_set_format(struct audio_stream *stream __unused,
6198 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006199{
6200 return -ENOSYS;
6201}
6202
6203static int in_standby(struct audio_stream *stream)
6204{
6205 struct stream_in *in = (struct stream_in *)stream;
6206 struct audio_device *adev = in->dev;
6207 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306208 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6209 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006210 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306211
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006212 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006213 if (!in->standby && in->is_st_session) {
6214 ALOGD("%s: sound trigger pcm stop lab", __func__);
6215 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006216 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006217 in->standby = 1;
6218 }
6219
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006220 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006221 if (adev->adm_deregister_stream)
6222 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6223
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006224 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006225 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006226 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006227 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006228 voice_extn_compress_voip_close_input_stream(stream);
6229 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006230 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6231 do_stop = in->capture_started;
6232 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006233 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306234 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05306235 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006236 }
6237
Arun Mirpuri5d170872019-03-26 13:21:31 -07006238 if (in->pcm) {
6239 ATRACE_BEGIN("pcm_in_close");
6240 pcm_close(in->pcm);
6241 ATRACE_END();
6242 in->pcm = NULL;
6243 }
6244
Carter Hsu2e429db2019-05-14 18:50:52 +08006245 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Aalique Grahame22e49102018-12-18 14:23:57 -08006246 adev->enable_voicerx = false;
Carter Hsu2e429db2019-05-14 18:50:52 +08006247
6248 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006249 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006250
6251 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6252 adev->num_va_sessions--;
6253
Eric Laurent150dbfe2013-02-27 14:31:02 -08006254 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006255 }
6256 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006257 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006258 return status;
6259}
6260
Aalique Grahame22e49102018-12-18 14:23:57 -08006261static int in_dump(const struct audio_stream *stream,
6262 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006263{
Aalique Grahame22e49102018-12-18 14:23:57 -08006264 struct stream_in *in = (struct stream_in *)stream;
6265
6266 // We try to get the lock for consistency,
6267 // but it isn't necessary for these variables.
6268 // If we're not in standby, we may be blocked on a read.
6269 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6270 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6271 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6272 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6273
6274 if (locked) {
6275 pthread_mutex_unlock(&in->lock);
6276 }
6277
6278 // dump error info
6279 (void)error_log_dump(
6280 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6281
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006282 return 0;
6283}
6284
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306285static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6286{
6287 if (!stream || !parms)
6288 return;
6289
6290 struct stream_in *in = (struct stream_in *)stream;
6291 struct audio_device *adev = in->dev;
6292
6293 card_status_t status;
6294 int card;
6295 if (parse_snd_card_status(parms, &card, &status) < 0)
6296 return;
6297
6298 pthread_mutex_lock(&adev->lock);
6299 bool valid_cb = (card == adev->snd_card);
6300 pthread_mutex_unlock(&adev->lock);
6301
6302 if (!valid_cb)
6303 return;
6304
6305 lock_input_stream(in);
6306 if (in->card_status != status)
6307 in->card_status = status;
6308 pthread_mutex_unlock(&in->lock);
6309
6310 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6311 use_case_table[in->usecase],
6312 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6313
6314 // a better solution would be to report error back to AF and let
6315 // it put the stream to standby
6316 if (status == CARD_STATUS_OFFLINE)
6317 in_standby(&in->stream.common);
6318
6319 return;
6320}
6321
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006322static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6323{
6324 struct stream_in *in = (struct stream_in *)stream;
6325 struct audio_device *adev = in->dev;
6326 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006327 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006328 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006329
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306330 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006331 parms = str_parms_create_str(kvpairs);
6332
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306333 if (!parms)
6334 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006335 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006336 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006337
6338 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6339 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006340 val = atoi(value);
6341 /* no audio source uses val == 0 */
6342 if ((in->source != val) && (val != 0)) {
6343 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006344 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6345 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6346 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006347 (in->config.rate == 8000 || in->config.rate == 16000 ||
6348 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006349 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006350 err = voice_extn_compress_voip_open_input_stream(in);
6351 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006352 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006353 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006354 }
6355 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006356 }
6357 }
6358
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006359 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6360 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006361 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006362 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6363
6364 // Workaround: If routing to an non existing usb device, fail gracefully
6365 // The routing request will otherwise block during 10 second
6366 int card;
6367 if (audio_is_usb_in_device(val) &&
6368 (card = get_alive_usb_card(parms)) >= 0) {
6369
6370 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6371 ret = -ENOSYS;
6372 } else {
6373
6374 in->device = val;
6375 /* If recording is in progress, change the tx device to new device */
6376 if (!in->standby && !in->is_st_session) {
6377 ALOGV("update input routing change");
6378 // inform adm before actual routing to prevent glitches.
6379 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006380 adev->adm_on_routing_change(adev->adm_data,
6381 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006382 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006383 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6384 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006385 }
6386 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006387 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006388 }
6389 }
6390
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306391 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6392 if (err >= 0) {
6393 strlcpy(in->profile, value, sizeof(in->profile));
6394 ALOGV("updating stream profile with value '%s'", in->profile);
6395 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6396 &adev->streams_input_cfg_list,
6397 in->device, in->flags, in->format,
6398 in->sample_rate, in->bit_width,
6399 in->profile, &in->app_type_cfg);
6400 }
6401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006402 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006403 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006404
6405 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306406error:
Eric Laurent994a6932013-07-17 11:51:42 -07006407 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006408 return ret;
6409}
6410
6411static char* in_get_parameters(const struct audio_stream *stream,
6412 const char *keys)
6413{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006414 struct stream_in *in = (struct stream_in *)stream;
6415 struct str_parms *query = str_parms_create_str(keys);
6416 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006417 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006418
6419 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006420 if (reply) {
6421 str_parms_destroy(reply);
6422 }
6423 if (query) {
6424 str_parms_destroy(query);
6425 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006426 ALOGE("in_get_parameters: failed to create query or reply");
6427 return NULL;
6428 }
6429
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006430 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006431
6432 voice_extn_in_get_parameters(in, query, reply);
6433
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006434 stream_get_parameter_channels(query, reply,
6435 &in->supported_channel_masks[0]);
6436 stream_get_parameter_formats(query, reply,
6437 &in->supported_formats[0]);
6438 stream_get_parameter_rates(query, reply,
6439 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006440 str = str_parms_to_str(reply);
6441 str_parms_destroy(query);
6442 str_parms_destroy(reply);
6443
6444 ALOGV("%s: exit: returns - %s", __func__, str);
6445 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006446}
6447
Aalique Grahame22e49102018-12-18 14:23:57 -08006448static int in_set_gain(struct audio_stream_in *stream,
6449 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006450{
Aalique Grahame22e49102018-12-18 14:23:57 -08006451 struct stream_in *in = (struct stream_in *)stream;
6452 char mixer_ctl_name[128];
6453 struct mixer_ctl *ctl;
6454 int ctl_value;
6455
6456 ALOGV("%s: gain %f", __func__, gain);
6457
6458 if (stream == NULL)
6459 return -EINVAL;
6460
6461 /* in_set_gain() only used to silence MMAP capture for now */
6462 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6463 return -ENOSYS;
6464
6465 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6466
6467 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6468 if (!ctl) {
6469 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6470 __func__, mixer_ctl_name);
6471 return -ENOSYS;
6472 }
6473
6474 if (gain < RECORD_GAIN_MIN)
6475 gain = RECORD_GAIN_MIN;
6476 else if (gain > RECORD_GAIN_MAX)
6477 gain = RECORD_GAIN_MAX;
6478 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6479
6480 mixer_ctl_set_value(ctl, 0, ctl_value);
6481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006482 return 0;
6483}
6484
6485static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6486 size_t bytes)
6487{
6488 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306489
6490 if (in == NULL) {
6491 ALOGE("%s: stream_in ptr is NULL", __func__);
6492 return -EINVAL;
6493 }
6494
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006495 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306496 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306497 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006498
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006499 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306500
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006501 if (in->is_st_session) {
6502 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6503 /* Read from sound trigger HAL */
6504 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006505 if (in->standby) {
6506 adev->num_va_sessions++;
6507 in->standby = 0;
6508 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006509 pthread_mutex_unlock(&in->lock);
6510 return bytes;
6511 }
6512
Haynes Mathew George16081042017-05-31 17:16:49 -07006513 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6514 ret = -ENOSYS;
6515 goto exit;
6516 }
6517
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006518 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6519 !in->standby && adev->adm_routing_changed) {
6520 ret = -ENOSYS;
6521 goto exit;
6522 }
6523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006524 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006525 pthread_mutex_lock(&adev->lock);
6526 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6527 ret = voice_extn_compress_voip_start_input_stream(in);
6528 else
6529 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006530 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6531 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006532 pthread_mutex_unlock(&adev->lock);
6533 if (ret != 0) {
6534 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006535 }
6536 in->standby = 0;
6537 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006538
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306539 /* Avoid read if capture_stopped is set */
6540 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6541 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6542 ret = -EINVAL;
6543 goto exit;
6544 }
6545
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006546 // what's the duration requested by the client?
6547 long ns = 0;
6548
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306549 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006550 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6551 in->config.rate;
6552
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006553 ret = request_in_focus(in, ns);
6554 if (ret != 0)
6555 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006556 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006557
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306558 if (audio_extn_cin_attached_usecase(in->usecase)) {
6559 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6560 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306561 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006562 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306563 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006564 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006565 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006566 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006567 } else if (audio_extn_ffv_get_stream() == in) {
6568 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306569 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006570 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306571 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6572 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6573 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6574 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306575 ret = -EINVAL;
6576 goto exit;
6577 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306578 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306579 ret = -errno;
6580 }
6581 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306582 /* bytes read is always set to bytes for non compress usecases */
6583 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006584 }
6585
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006586 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006588 /*
Quinn Malef6050362019-01-30 15:55:40 -08006589 * Instead of writing zeroes here, we could trust the hardware to always
6590 * provide zeroes when muted. This is also muted with voice recognition
6591 * usecases so that other clients do not have access to voice recognition
6592 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006593 */
Quinn Malef6050362019-01-30 15:55:40 -08006594 if ((ret == 0 && voice_get_mic_mute(adev) &&
6595 !voice_is_in_call_rec_stream(in) &&
6596 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6597 (adev->num_va_sessions &&
6598 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6599 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6600 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006601 memset(buffer, 0, bytes);
6602
6603exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306604 frame_size = audio_stream_in_frame_size(stream);
6605 if (frame_size > 0)
6606 in->frames_read += bytes_read/frame_size;
6607
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006608 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306609 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006610 pthread_mutex_unlock(&in->lock);
6611
6612 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306613 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306614 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306615 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306616 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306617 in->standby = true;
6618 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306619 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6620 bytes_read = bytes;
6621 memset(buffer, 0, bytes);
6622 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006623 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006624 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6625 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006626 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306627 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306628 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006629 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306630 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006631}
6632
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006633static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006634{
6635 return 0;
6636}
6637
Aalique Grahame22e49102018-12-18 14:23:57 -08006638static int in_get_capture_position(const struct audio_stream_in *stream,
6639 int64_t *frames, int64_t *time)
6640{
6641 if (stream == NULL || frames == NULL || time == NULL) {
6642 return -EINVAL;
6643 }
6644 struct stream_in *in = (struct stream_in *)stream;
6645 int ret = -ENOSYS;
6646
6647 lock_input_stream(in);
6648 // note: ST sessions do not close the alsa pcm driver synchronously
6649 // on standby. Therefore, we may return an error even though the
6650 // pcm stream is still opened.
6651 if (in->standby) {
6652 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6653 "%s stream in standby but pcm not NULL for non ST session", __func__);
6654 goto exit;
6655 }
6656 if (in->pcm) {
6657 struct timespec timestamp;
6658 unsigned int avail;
6659 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6660 *frames = in->frames_read + avail;
6661 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6662 ret = 0;
6663 }
6664 }
6665exit:
6666 pthread_mutex_unlock(&in->lock);
6667 return ret;
6668}
6669
Carter Hsu2e429db2019-05-14 18:50:52 +08006670static int in_update_effect_list(bool add, effect_handle_t effect,
6671 struct listnode *head)
6672{
6673 struct listnode *node;
6674 struct in_effect_list *elist = NULL;
6675 struct in_effect_list *target = NULL;
6676 int ret = 0;
6677
6678 if (!head)
6679 return ret;
6680
6681 list_for_each(node, head) {
6682 elist = node_to_item(node, struct in_effect_list, list);
6683 if (elist->handle == effect) {
6684 target = elist;
6685 break;
6686 }
6687 }
6688
6689 if (add) {
6690 if (target) {
6691 ALOGD("effect %p already exist", effect);
6692 return ret;
6693 }
6694
6695 target = (struct in_effect_list *)
6696 calloc(1, sizeof(struct in_effect_list));
6697
6698 if (!target) {
6699 ALOGE("%s:fail to allocate memory", __func__);
6700 return -ENOMEM;
6701 }
6702
6703 target->handle = effect;
6704 list_add_tail(head, &target->list);
6705 } else {
6706 if (target) {
6707 list_remove(&target->list);
6708 free(target);
6709 }
6710 }
6711
6712 return ret;
6713}
6714
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006715static int add_remove_audio_effect(const struct audio_stream *stream,
6716 effect_handle_t effect,
6717 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006718{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006719 struct stream_in *in = (struct stream_in *)stream;
6720 int status = 0;
6721 effect_descriptor_t desc;
6722
6723 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006724 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6725
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006726 if (status != 0)
6727 return status;
6728
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006729 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006730 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006731 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08006732 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
6733 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006734 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08006735
6736 in_update_effect_list(enable, effect, &in->aec_list);
6737 enable = !list_empty(&in->aec_list);
6738 if (enable == in->enable_aec)
6739 goto exit;
6740
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006741 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006742 ALOGD("AEC enable %d", enable);
6743
Aalique Grahame22e49102018-12-18 14:23:57 -08006744 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6745 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6746 in->dev->enable_voicerx = enable;
6747 struct audio_usecase *usecase;
6748 struct listnode *node;
6749 list_for_each(node, &in->dev->usecase_list) {
6750 usecase = node_to_item(node, struct audio_usecase, list);
6751 if (usecase->type == PCM_PLAYBACK)
6752 select_devices(in->dev, usecase->id);
6753 }
6754 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006755 if (!in->standby) {
6756 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6757 select_devices(in->dev, in->usecase);
6758 }
6759
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006760 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006761 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
6762
6763 in_update_effect_list(enable, effect, &in->ns_list);
6764 enable = !list_empty(&in->ns_list);
6765 if (enable == in->enable_ns)
6766 goto exit;
6767
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006768 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006769 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006770 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006771 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6772 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006773 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6774 select_devices(in->dev, in->usecase);
6775 } else
6776 select_devices(in->dev, in->usecase);
6777 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006778 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006779exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006780 pthread_mutex_unlock(&in->dev->lock);
6781 pthread_mutex_unlock(&in->lock);
6782
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006783 return 0;
6784}
6785
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006786static int in_add_audio_effect(const struct audio_stream *stream,
6787 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006788{
Eric Laurent994a6932013-07-17 11:51:42 -07006789 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006790 return add_remove_audio_effect(stream, effect, true);
6791}
6792
6793static int in_remove_audio_effect(const struct audio_stream *stream,
6794 effect_handle_t effect)
6795{
Eric Laurent994a6932013-07-17 11:51:42 -07006796 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006797 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006798}
6799
Derek Chenf939fb72018-11-13 13:34:41 -08006800streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6801 audio_io_handle_t input)
6802{
6803 struct listnode *node;
6804
6805 list_for_each(node, &dev->active_inputs_list) {
6806 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6807 streams_input_ctxt_t,
6808 list);
6809 if (in_ctxt->input->capture_handle == input) {
6810 return in_ctxt;
6811 }
6812 }
6813 return NULL;
6814}
6815
6816streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6817 audio_io_handle_t output)
6818{
6819 struct listnode *node;
6820
6821 list_for_each(node, &dev->active_outputs_list) {
6822 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6823 streams_output_ctxt_t,
6824 list);
6825 if (out_ctxt->output->handle == output) {
6826 return out_ctxt;
6827 }
6828 }
6829 return NULL;
6830}
6831
Haynes Mathew George16081042017-05-31 17:16:49 -07006832static int in_stop(const struct audio_stream_in* stream)
6833{
6834 struct stream_in *in = (struct stream_in *)stream;
6835 struct audio_device *adev = in->dev;
6836
6837 int ret = -ENOSYS;
6838 ALOGV("%s", __func__);
6839 pthread_mutex_lock(&adev->lock);
6840 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6841 in->capture_started && in->pcm != NULL) {
6842 pcm_stop(in->pcm);
6843 ret = stop_input_stream(in);
6844 in->capture_started = false;
6845 }
6846 pthread_mutex_unlock(&adev->lock);
6847 return ret;
6848}
6849
6850static int in_start(const struct audio_stream_in* stream)
6851{
6852 struct stream_in *in = (struct stream_in *)stream;
6853 struct audio_device *adev = in->dev;
6854 int ret = -ENOSYS;
6855
6856 ALOGV("%s in %p", __func__, in);
6857 pthread_mutex_lock(&adev->lock);
6858 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6859 !in->capture_started && in->pcm != NULL) {
6860 if (!in->capture_started) {
6861 ret = start_input_stream(in);
6862 if (ret == 0) {
6863 in->capture_started = true;
6864 }
6865 }
6866 }
6867 pthread_mutex_unlock(&adev->lock);
6868 return ret;
6869}
6870
Phil Burke0a86d12019-02-16 22:28:11 -08006871// Read offset for the positional timestamp from a persistent vendor property.
6872// This is to workaround apparent inaccuracies in the timing information that
6873// is used by the AAudio timing model. The inaccuracies can cause glitches.
6874static int64_t in_get_mmap_time_offset() {
6875 const int32_t kDefaultOffsetMicros = 0;
6876 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006877 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006878 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6879 return mmap_time_offset_micros * (int64_t)1000;
6880}
6881
Haynes Mathew George16081042017-05-31 17:16:49 -07006882static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6883 int32_t min_size_frames,
6884 struct audio_mmap_buffer_info *info)
6885{
6886 struct stream_in *in = (struct stream_in *)stream;
6887 struct audio_device *adev = in->dev;
6888 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006889 unsigned int offset1 = 0;
6890 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006891 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006892 uint32_t mmap_size = 0;
6893 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006894
6895 pthread_mutex_lock(&adev->lock);
6896 ALOGV("%s in %p", __func__, in);
6897
Sharad Sanglec6f32552018-05-04 16:15:38 +05306898 if (CARD_STATUS_OFFLINE == in->card_status||
6899 CARD_STATUS_OFFLINE == adev->card_status) {
6900 ALOGW("in->card_status or adev->card_status offline, try again");
6901 ret = -EIO;
6902 goto exit;
6903 }
6904
Haynes Mathew George16081042017-05-31 17:16:49 -07006905 if (info == NULL || min_size_frames == 0) {
6906 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6907 ret = -EINVAL;
6908 goto exit;
6909 }
6910 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6911 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6912 ALOGV("%s in %p", __func__, in);
6913 ret = -ENOSYS;
6914 goto exit;
6915 }
6916 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6917 if (in->pcm_device_id < 0) {
6918 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6919 __func__, in->pcm_device_id, in->usecase);
6920 ret = -EINVAL;
6921 goto exit;
6922 }
6923
6924 adjust_mmap_period_count(&in->config, min_size_frames);
6925
6926 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6927 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6928 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6929 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306930 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306931 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6932 in->card_status = CARD_STATUS_OFFLINE;
6933 adev->card_status = CARD_STATUS_OFFLINE;
6934 ret = -EIO;
6935 goto exit;
6936 }
6937
Haynes Mathew George16081042017-05-31 17:16:49 -07006938 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6939 step = "open";
6940 ret = -ENODEV;
6941 goto exit;
6942 }
6943
6944 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6945 if (ret < 0) {
6946 step = "begin";
6947 goto exit;
6948 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006949
Arun Mirpuri5d170872019-03-26 13:21:31 -07006950 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6951 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6952 info->burst_size_frames = in->config.period_size;
6953 ret = platform_get_mmap_data_fd(adev->platform,
6954 in->pcm_device_id, 1 /*capture*/,
6955 &info->shared_memory_fd,
6956 &mmap_size);
6957 if (ret < 0) {
6958 // Fall back to non exclusive mode
6959 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6960 } else {
6961 if (mmap_size < buffer_size) {
6962 step = "mmap";
6963 goto exit;
6964 }
6965 // FIXME: indicate exclusive mode support by returning a negative buffer size
6966 info->buffer_size_frames *= -1;
6967 }
6968
6969 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006970
6971 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6972 if (ret < 0) {
6973 step = "commit";
6974 goto exit;
6975 }
6976
Phil Burke0a86d12019-02-16 22:28:11 -08006977 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
6978
Haynes Mathew George16081042017-05-31 17:16:49 -07006979 in->standby = false;
6980 ret = 0;
6981
6982 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6983 __func__, info->shared_memory_address, info->buffer_size_frames);
6984
6985exit:
6986 if (ret != 0) {
6987 if (in->pcm == NULL) {
6988 ALOGE("%s: %s - %d", __func__, step, ret);
6989 } else {
6990 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6991 pcm_close(in->pcm);
6992 in->pcm = NULL;
6993 }
6994 }
6995 pthread_mutex_unlock(&adev->lock);
6996 return ret;
6997}
6998
6999static int in_get_mmap_position(const struct audio_stream_in *stream,
7000 struct audio_mmap_position *position)
7001{
7002 struct stream_in *in = (struct stream_in *)stream;
7003 ALOGVV("%s", __func__);
7004 if (position == NULL) {
7005 return -EINVAL;
7006 }
7007 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7008 return -ENOSYS;
7009 }
7010 if (in->pcm == NULL) {
7011 return -ENOSYS;
7012 }
7013 struct timespec ts = { 0, 0 };
7014 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7015 if (ret < 0) {
7016 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7017 return ret;
7018 }
Phil Burke0a86d12019-02-16 22:28:11 -08007019 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7020 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007021 return 0;
7022}
7023
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307024static int in_get_active_microphones(const struct audio_stream_in *stream,
7025 struct audio_microphone_characteristic_t *mic_array,
7026 size_t *mic_count) {
7027 struct stream_in *in = (struct stream_in *)stream;
7028 struct audio_device *adev = in->dev;
7029 ALOGVV("%s", __func__);
7030
7031 lock_input_stream(in);
7032 pthread_mutex_lock(&adev->lock);
7033 int ret = platform_get_active_microphones(adev->platform,
7034 audio_channel_count_from_in_mask(in->channel_mask),
7035 in->usecase, mic_array, mic_count);
7036 pthread_mutex_unlock(&adev->lock);
7037 pthread_mutex_unlock(&in->lock);
7038
7039 return ret;
7040}
7041
7042static int adev_get_microphones(const struct audio_hw_device *dev,
7043 struct audio_microphone_characteristic_t *mic_array,
7044 size_t *mic_count) {
7045 struct audio_device *adev = (struct audio_device *)dev;
7046 ALOGVV("%s", __func__);
7047
7048 pthread_mutex_lock(&adev->lock);
7049 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7050 pthread_mutex_unlock(&adev->lock);
7051
7052 return ret;
7053}
juyuchendb308c22019-01-21 11:57:17 -07007054
7055static void in_update_sink_metadata(struct audio_stream_in *stream,
7056 const struct sink_metadata *sink_metadata) {
7057
7058 if (stream == NULL
7059 || sink_metadata == NULL
7060 || sink_metadata->tracks == NULL) {
7061 return;
7062 }
7063
7064 int error = 0;
7065 struct stream_in *in = (struct stream_in *)stream;
7066 struct audio_device *adev = in->dev;
7067 audio_devices_t device = AUDIO_DEVICE_NONE;
7068
7069 if (sink_metadata->track_count != 0)
7070 device = sink_metadata->tracks->dest_device;
7071
7072 lock_input_stream(in);
7073 pthread_mutex_lock(&adev->lock);
7074 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
7075
7076 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
7077 && device != AUDIO_DEVICE_NONE
7078 && adev->voice_tx_output != NULL) {
7079 /* Use the rx device from afe-proxy record to route voice call because
7080 there is no routing if tx device is on primary hal and rx device
7081 is on other hal during voice call. */
7082 adev->voice_tx_output->devices = device;
7083
7084 if (!voice_is_call_state_active(adev)) {
7085 if (adev->mode == AUDIO_MODE_IN_CALL) {
7086 adev->current_call_output = adev->voice_tx_output;
7087 error = voice_start_call(adev);
7088 if (error != 0)
7089 ALOGE("%s: start voice call failed %d", __func__, error);
7090 }
7091 } else {
7092 adev->current_call_output = adev->voice_tx_output;
7093 voice_update_devices_for_all_voice_usecases(adev);
7094 }
7095 }
7096
7097 pthread_mutex_unlock(&adev->lock);
7098 pthread_mutex_unlock(&in->lock);
7099}
7100
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307101int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007102 audio_io_handle_t handle,
7103 audio_devices_t devices,
7104 audio_output_flags_t flags,
7105 struct audio_config *config,
7106 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007107 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007108{
7109 struct audio_device *adev = (struct audio_device *)dev;
7110 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307111 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007112 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007113 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307114 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007115 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7116 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7117 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7118 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007119 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007120 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7121 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007122 bool force_haptic_path =
7123 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007124 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007125
kunleizdff872d2018-08-20 14:40:33 +08007126 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007127 is_usb_dev = false;
7128 devices = AUDIO_DEVICE_OUT_SPEAKER;
7129 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7130 __func__, devices);
7131 }
7132
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007133 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007135 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7136
Mingming Yin3a941d42016-02-17 18:08:05 -08007137 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007138 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7139 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307140
7141
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007142 if (!out) {
7143 return -ENOMEM;
7144 }
7145
Haynes Mathew George204045b2015-02-25 20:32:03 -08007146 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007147 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307148 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007149 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007150 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007152 if (devices == AUDIO_DEVICE_NONE)
7153 devices = AUDIO_DEVICE_OUT_SPEAKER;
7154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007155 out->flags = flags;
7156 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007157 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007158 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007159 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307160 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307161 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7162 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7163 else
7164 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007165 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007166 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007167 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307168 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307169 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307170 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007171 out->hal_output_suspend_supported = 0;
7172 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307173 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307174 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307175 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007176
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307177 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307178 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007179 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7180
Aalique Grahame22e49102018-12-18 14:23:57 -08007181 if (direct_dev &&
7182 (audio_is_linear_pcm(out->format) ||
7183 config->format == AUDIO_FORMAT_DEFAULT) &&
7184 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7185 audio_format_t req_format = config->format;
7186 audio_channel_mask_t req_channel_mask = config->channel_mask;
7187 uint32_t req_sample_rate = config->sample_rate;
7188
7189 pthread_mutex_lock(&adev->lock);
7190 if (is_hdmi) {
7191 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7192 ret = read_hdmi_sink_caps(out);
7193 if (config->sample_rate == 0)
7194 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7195 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7196 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7197 if (config->format == AUDIO_FORMAT_DEFAULT)
7198 config->format = AUDIO_FORMAT_PCM_16_BIT;
7199 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007200 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7201 &config->format,
7202 &out->supported_formats[0],
7203 MAX_SUPPORTED_FORMATS,
7204 &config->channel_mask,
7205 &out->supported_channel_masks[0],
7206 MAX_SUPPORTED_CHANNEL_MASKS,
7207 &config->sample_rate,
7208 &out->supported_sample_rates[0],
7209 MAX_SUPPORTED_SAMPLE_RATES);
7210 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007211 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007212
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007213 pthread_mutex_unlock(&adev->lock);
7214 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007215 if (ret == -ENOSYS) {
7216 /* ignore and go with default */
7217 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007218 }
7219 // For MMAP NO IRQ, allow conversions in ADSP
7220 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7221 goto error_open;
7222 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007223 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007224 goto error_open;
7225 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007226
7227 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7228 config->sample_rate = req_sample_rate;
7229 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7230 config->channel_mask = req_channel_mask;
7231 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7232 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007233 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007234
7235 out->sample_rate = config->sample_rate;
7236 out->channel_mask = config->channel_mask;
7237 out->format = config->format;
7238 if (is_hdmi) {
7239 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7240 out->config = pcm_config_hdmi_multi;
7241 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7242 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7243 out->config = pcm_config_mmap_playback;
7244 out->stream.start = out_start;
7245 out->stream.stop = out_stop;
7246 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7247 out->stream.get_mmap_position = out_get_mmap_position;
7248 } else {
7249 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7250 out->config = pcm_config_hifi;
7251 }
7252
7253 out->config.rate = out->sample_rate;
7254 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7255 if (is_hdmi) {
7256 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7257 audio_bytes_per_sample(out->format));
7258 }
7259 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007260 }
7261
Derek Chenf6318be2017-06-12 17:16:24 -04007262 /* validate bus device address */
7263 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7264 /* extract car audio stream index */
7265 out->car_audio_stream =
7266 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7267 if (out->car_audio_stream < 0) {
7268 ALOGE("%s: invalid car audio stream %x",
7269 __func__, out->car_audio_stream);
7270 ret = -EINVAL;
7271 goto error_open;
7272 }
7273 /* save car audio stream and address for bus device */
7274 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
7275 ALOGV("%s: address %s, car_audio_stream %x",
7276 __func__, out->address, out->car_audio_stream);
7277 }
7278
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007279 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007280 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007281 if (!voice_extn_is_compress_voip_supported()) {
7282 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7283 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007284 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7285 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007286 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7287 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007288 out->volume_l = INVALID_OUT_VOLUME;
7289 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007290
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007291 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007292 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007293 uint32_t channel_count =
7294 audio_channel_count_from_out_mask(out->channel_mask);
7295 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7296 out->sample_rate, out->format,
7297 channel_count, false);
7298 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7299 if (frame_size != 0)
7300 out->config.period_size = buffer_size / frame_size;
7301 else
7302 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007303 }
7304 } else {
7305 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7306 voice_extn_compress_voip_is_active(out->dev)) &&
7307 (voice_extn_compress_voip_is_config_supported(config))) {
7308 ret = voice_extn_compress_voip_open_output_stream(out);
7309 if (ret != 0) {
7310 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7311 __func__, ret);
7312 goto error_open;
7313 }
7314 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007315 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007316 } else if (audio_is_linear_pcm(out->format) &&
7317 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7318 out->channel_mask = config->channel_mask;
7319 out->sample_rate = config->sample_rate;
7320 out->format = config->format;
7321 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7322 // does this change?
7323 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7324 out->config.rate = config->sample_rate;
7325 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7326 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7327 audio_bytes_per_sample(config->format));
7328 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007329 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307330 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307331 pthread_mutex_lock(&adev->lock);
7332 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7333 pthread_mutex_unlock(&adev->lock);
7334
7335 // reject offload during card offline to allow
7336 // fallback to s/w paths
7337 if (offline) {
7338 ret = -ENODEV;
7339 goto error_open;
7340 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007341
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007342 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7343 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7344 ALOGE("%s: Unsupported Offload information", __func__);
7345 ret = -EINVAL;
7346 goto error_open;
7347 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007348
Atul Khare3fa6e542017-08-09 00:56:17 +05307349 if (config->offload_info.format == 0)
7350 config->offload_info.format = config->format;
7351 if (config->offload_info.sample_rate == 0)
7352 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007353
Mingming Yin90310102013-11-13 16:57:00 -08007354 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307355 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007356 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007357 ret = -EINVAL;
7358 goto error_open;
7359 }
7360
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007361 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7362 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7363 (audio_extn_passthru_is_passthrough_stream(out)) &&
7364 !((config->sample_rate == 48000) ||
7365 (config->sample_rate == 96000) ||
7366 (config->sample_rate == 192000))) {
7367 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7368 __func__, config->sample_rate, config->offload_info.format);
7369 ret = -EINVAL;
7370 goto error_open;
7371 }
7372
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007373 out->compr_config.codec = (struct snd_codec *)
7374 calloc(1, sizeof(struct snd_codec));
7375
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007376 if (!out->compr_config.codec) {
7377 ret = -ENOMEM;
7378 goto error_open;
7379 }
7380
Dhananjay Kumarac341582017-02-23 23:42:25 +05307381 out->stream.pause = out_pause;
7382 out->stream.resume = out_resume;
7383 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307384 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307385 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007386 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307387 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007388 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307389 } else {
7390 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7391 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007392 }
vivek mehta446c3962015-09-14 10:57:35 -07007393
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307394 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7395 ALOGD("%s: Setting latency mode to true", __func__);
7396 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
7397 }
7398
vivek mehta446c3962015-09-14 10:57:35 -07007399 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007400 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7401 config->format == 0 && config->sample_rate == 0 &&
7402 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007403 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007404 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7405 } else {
7406 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7407 ret = -EEXIST;
7408 goto error_open;
7409 }
vivek mehta446c3962015-09-14 10:57:35 -07007410 }
7411
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007412 if (config->offload_info.channel_mask)
7413 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007414 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007415 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007416 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007417 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307418 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007419 ret = -EINVAL;
7420 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007421 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007422
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007423 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007424 out->sample_rate = config->offload_info.sample_rate;
7425
Mingming Yin3ee55c62014-08-04 14:23:35 -07007426 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007427
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307428 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307429 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307430 audio_extn_dolby_send_ddp_endp_params(adev);
7431 audio_extn_dolby_set_dmid(adev);
7432 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007433
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007434 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007435 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007436 out->compr_config.codec->bit_rate =
7437 config->offload_info.bit_rate;
7438 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307439 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007440 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307441 /* Update bit width only for non passthrough usecases.
7442 * For passthrough usecases, the output will always be opened @16 bit
7443 */
7444 if (!audio_extn_passthru_is_passthrough_stream(out))
7445 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307446
7447 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7448 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7449 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7450
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007451 /*TODO: Do we need to change it for passthrough */
7452 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007453
Manish Dewangana6fc5442015-08-24 20:30:31 +05307454 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7455 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307456 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307457 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307458 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7459 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307460
7461 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7462 AUDIO_FORMAT_PCM) {
7463
7464 /*Based on platform support, configure appropriate alsa format for corresponding
7465 *hal input format.
7466 */
7467 out->compr_config.codec->format = hal_format_to_alsa(
7468 config->offload_info.format);
7469
Ashish Jain83a6cc22016-06-28 14:34:17 +05307470 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307471 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307472 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307473
Dhananjay Kumarac341582017-02-23 23:42:25 +05307474 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307475 *hal input format and alsa format might differ based on platform support.
7476 */
7477 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307478 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307479
7480 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7481
Deeraj Soman65358ab2019-02-07 15:40:49 +05307482 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7483 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7484 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7485
Ashish Jainf1eaa582016-05-23 20:54:24 +05307486 /* Check if alsa session is configured with the same format as HAL input format,
7487 * if not then derive correct fragment size needed to accomodate the
7488 * conversion of HAL input format to alsa format.
7489 */
7490 audio_extn_utils_update_direct_pcm_fragment_size(out);
7491
7492 /*if hal input and output fragment size is different this indicates HAL input format is
7493 *not same as the alsa format
7494 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307495 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307496 /*Allocate a buffer to convert input data to the alsa configured format.
7497 *size of convert buffer is equal to the size required to hold one fragment size
7498 *worth of pcm data, this is because flinger does not write more than fragment_size
7499 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307500 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7501 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307502 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7503 ret = -ENOMEM;
7504 goto error_open;
7505 }
7506 }
7507 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7508 out->compr_config.fragment_size =
7509 audio_extn_passthru_get_buffer_size(&config->offload_info);
7510 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7511 } else {
7512 out->compr_config.fragment_size =
7513 platform_get_compress_offload_buffer_size(&config->offload_info);
7514 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7515 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007516
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307517 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7518 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7519 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007520 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307521 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007522
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307523 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7524 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7525 }
7526
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007527 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7528 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007529
Manish Dewangan69426c82017-01-30 17:35:36 +05307530 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7531 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7532 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7533 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7534 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7535 } else {
7536 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7537 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007538
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307539 memset(&out->channel_map_param, 0,
7540 sizeof(struct audio_out_channel_map_param));
7541
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007542 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307543 out->send_next_track_params = false;
7544 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007545 out->offload_state = OFFLOAD_STATE_IDLE;
7546 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007547 out->writeAt.tv_sec = 0;
7548 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007549
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007550 audio_extn_dts_create_state_notifier_node(out->usecase);
7551
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007552 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7553 __func__, config->offload_info.version,
7554 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307555
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307556 /* Check if DSD audio format is supported in codec
7557 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307558 */
7559
7560 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307561 (!platform_check_codec_dsd_support(adev->platform) ||
7562 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307563 ret = -EINVAL;
7564 goto error_open;
7565 }
7566
Ashish Jain5106d362016-05-11 19:23:33 +05307567 /* Disable gapless if any of the following is true
7568 * passthrough playback
7569 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307570 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307571 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307572 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307573 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007574 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307575 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307576 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307577 check_and_set_gapless_mode(adev, false);
7578 } else
7579 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007580
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307581 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007582 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7583 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307584 if (config->format == AUDIO_FORMAT_DSD) {
7585 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7586 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7587 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007588
7589 create_offload_callback_thread(out);
7590
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007591 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007592 switch (config->sample_rate) {
7593 case 0:
7594 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7595 break;
7596 case 8000:
7597 case 16000:
7598 case 48000:
7599 out->sample_rate = config->sample_rate;
7600 break;
7601 default:
7602 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7603 config->sample_rate);
7604 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7605 ret = -EINVAL;
7606 goto error_open;
7607 }
7608 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7609 switch (config->channel_mask) {
7610 case AUDIO_CHANNEL_NONE:
7611 case AUDIO_CHANNEL_OUT_STEREO:
7612 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7613 break;
7614 default:
7615 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7616 config->channel_mask);
7617 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7618 ret = -EINVAL;
7619 goto error_open;
7620 }
7621 switch (config->format) {
7622 case AUDIO_FORMAT_DEFAULT:
7623 case AUDIO_FORMAT_PCM_16_BIT:
7624 out->format = AUDIO_FORMAT_PCM_16_BIT;
7625 break;
7626 default:
7627 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7628 config->format);
7629 config->format = AUDIO_FORMAT_PCM_16_BIT;
7630 ret = -EINVAL;
7631 goto error_open;
7632 }
7633
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307634 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007635 if (ret != 0) {
7636 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007637 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007638 goto error_open;
7639 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007640 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007641 switch (config->sample_rate) {
7642 case 0:
7643 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7644 break;
7645 case 8000:
7646 case 16000:
7647 case 48000:
7648 out->sample_rate = config->sample_rate;
7649 break;
7650 default:
7651 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7652 config->sample_rate);
7653 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7654 ret = -EINVAL;
7655 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007656 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007657 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7658 switch (config->channel_mask) {
7659 case AUDIO_CHANNEL_NONE:
7660 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7661 break;
7662 case AUDIO_CHANNEL_OUT_STEREO:
7663 out->channel_mask = config->channel_mask;
7664 break;
7665 default:
7666 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7667 config->channel_mask);
7668 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7669 ret = -EINVAL;
7670 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007671 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007672 switch (config->format) {
7673 case AUDIO_FORMAT_DEFAULT:
7674 out->format = AUDIO_FORMAT_PCM_16_BIT;
7675 break;
7676 case AUDIO_FORMAT_PCM_16_BIT:
7677 out->format = config->format;
7678 break;
7679 default:
7680 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7681 config->format);
7682 config->format = AUDIO_FORMAT_PCM_16_BIT;
7683 ret = -EINVAL;
7684 break;
7685 }
7686 if (ret != 0)
7687 goto error_open;
7688
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007689 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7690 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007691 out->config.rate = out->sample_rate;
7692 out->config.channels =
7693 audio_channel_count_from_out_mask(out->channel_mask);
7694 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007695 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007696 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307697 unsigned int channels = 0;
7698 /*Update config params to default if not set by the caller*/
7699 if (config->sample_rate == 0)
7700 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7701 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7702 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7703 if (config->format == AUDIO_FORMAT_DEFAULT)
7704 config->format = AUDIO_FORMAT_PCM_16_BIT;
7705
7706 channels = audio_channel_count_from_out_mask(out->channel_mask);
7707
Varun Balaraje49253e2017-07-06 19:48:56 +05307708 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7709 out->usecase = get_interactive_usecase(adev);
7710 out->config = pcm_config_low_latency;
7711 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307712 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007713 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7714 out->flags);
7715 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007716 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7717 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7718 out->config = pcm_config_mmap_playback;
7719 out->stream.start = out_start;
7720 out->stream.stop = out_stop;
7721 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7722 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307723 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7724 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007725 out->hal_output_suspend_supported =
7726 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7727 out->dynamic_pm_qos_config_supported =
7728 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7729 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007730 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7731 } else {
7732 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7733 //the mixer path will be a string similar to "low-latency-playback resume"
7734 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7735 strlcat(out->pm_qos_mixer_path,
7736 " resume", MAX_MIXER_PATH_LEN);
7737 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7738 out->pm_qos_mixer_path);
7739 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307740 out->config = pcm_config_low_latency;
7741 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7742 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7743 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307744 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7745 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7746 if (out->config.period_size <= 0) {
7747 ALOGE("Invalid configuration period size is not valid");
7748 ret = -EINVAL;
7749 goto error_open;
7750 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007751 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7752 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7753 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007754 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7755 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7756 out->config = pcm_config_haptics_audio;
7757 if (force_haptic_path)
7758 adev->haptics_config = pcm_config_haptics_audio;
7759 else
7760 adev->haptics_config = pcm_config_haptics;
7761
7762 out->config.channels =
7763 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7764
7765 if (force_haptic_path) {
7766 out->config.channels = 1;
7767 adev->haptics_config.channels = 1;
7768 } else
7769 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Derek Chenf6318be2017-06-12 17:16:24 -04007770 } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7771 ret = audio_extn_auto_hal_open_output_stream(out);
7772 if (ret) {
7773 ALOGE("%s: Failed to open output stream for bus device", __func__);
7774 ret = -EINVAL;
7775 goto error_open;
7776 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307777 } else {
7778 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007779 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7780 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307781 }
7782 out->hal_ip_format = format = out->format;
7783 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7784 out->hal_op_format = pcm_format_to_hal(out->config.format);
7785 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7786 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007787 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307788 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307789 if (out->hal_ip_format != out->hal_op_format) {
7790 uint32_t buffer_size = out->config.period_size *
7791 format_to_bitwidth_table[out->hal_op_format] *
7792 out->config.channels;
7793 out->convert_buffer = calloc(1, buffer_size);
7794 if (out->convert_buffer == NULL){
7795 ALOGE("Allocation failed for convert buffer for size %d",
7796 out->compr_config.fragment_size);
7797 ret = -ENOMEM;
7798 goto error_open;
7799 }
7800 ALOGD("Convert buffer allocated of size %d", buffer_size);
7801 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007802 }
7803
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007804 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7805 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307806
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007807 /* TODO remove this hardcoding and check why width is zero*/
7808 if (out->bit_width == 0)
7809 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307810 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007811 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007812 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307813 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307814 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007815 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007816 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7817 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007818 if(adev->primary_output == NULL)
7819 adev->primary_output = out;
7820 else {
7821 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007822 ret = -EEXIST;
7823 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007824 }
7825 }
7826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007827 /* Check if this usecase is already existing */
7828 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007829 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7830 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007831 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007832 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007833 ret = -EEXIST;
7834 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007835 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007836
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007837 pthread_mutex_unlock(&adev->lock);
7838
7839 out->stream.common.get_sample_rate = out_get_sample_rate;
7840 out->stream.common.set_sample_rate = out_set_sample_rate;
7841 out->stream.common.get_buffer_size = out_get_buffer_size;
7842 out->stream.common.get_channels = out_get_channels;
7843 out->stream.common.get_format = out_get_format;
7844 out->stream.common.set_format = out_set_format;
7845 out->stream.common.standby = out_standby;
7846 out->stream.common.dump = out_dump;
7847 out->stream.common.set_parameters = out_set_parameters;
7848 out->stream.common.get_parameters = out_get_parameters;
7849 out->stream.common.add_audio_effect = out_add_audio_effect;
7850 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7851 out->stream.get_latency = out_get_latency;
7852 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007853#ifdef NO_AUDIO_OUT
7854 out->stream.write = out_write_for_no_output;
7855#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007856 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007857#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007858 out->stream.get_render_position = out_get_render_position;
7859 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007860 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007861
Haynes Mathew George16081042017-05-31 17:16:49 -07007862 if (out->realtime)
7863 out->af_period_multiplier = af_period_multiplier;
7864 else
7865 out->af_period_multiplier = 1;
7866
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007867 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007868 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007869 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007870
7871 config->format = out->stream.common.get_format(&out->stream.common);
7872 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7873 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307874 register_format(out->format, out->supported_formats);
7875 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7876 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007877
Aalique Grahame22e49102018-12-18 14:23:57 -08007878 out->error_log = error_log_create(
7879 ERROR_LOG_ENTRIES,
7880 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7881
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307882 /*
7883 By locking output stream before registering, we allow the callback
7884 to update stream's state only after stream's initial state is set to
7885 adev state.
7886 */
7887 lock_output_stream(out);
7888 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7889 pthread_mutex_lock(&adev->lock);
7890 out->card_status = adev->card_status;
7891 pthread_mutex_unlock(&adev->lock);
7892 pthread_mutex_unlock(&out->lock);
7893
Aalique Grahame22e49102018-12-18 14:23:57 -08007894 stream_app_type_cfg_init(&out->app_type_cfg);
7895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007896 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307897 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007898 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007899
7900 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7901 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7902 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007903 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307904 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007905 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007906 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307907 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
7908 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007909 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7910 out->usecase, PCM_PLAYBACK);
7911 hdlr_stream_cfg.flags = out->flags;
7912 hdlr_stream_cfg.type = PCM_PLAYBACK;
7913 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7914 &hdlr_stream_cfg);
7915 if (ret) {
7916 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7917 out->adsp_hdlr_stream_handle = NULL;
7918 }
7919 }
Gangadhar Sb0210342019-02-22 17:39:41 +05307920 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
7921 is_direct_passthough, false);
7922 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
7923 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007924 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007925 if (ret < 0) {
7926 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7927 out->ip_hdlr_handle = NULL;
7928 }
7929 }
Derek Chenf939fb72018-11-13 13:34:41 -08007930
7931 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7932 calloc(1, sizeof(streams_output_ctxt_t));
7933 if (out_ctxt == NULL) {
7934 ALOGE("%s fail to allocate output ctxt", __func__);
7935 ret = -ENOMEM;
7936 goto error_open;
7937 }
7938 out_ctxt->output = out;
7939
7940 pthread_mutex_lock(&adev->lock);
7941 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7942 pthread_mutex_unlock(&adev->lock);
7943
Eric Laurent994a6932013-07-17 11:51:42 -07007944 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007945 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007946
7947error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307948 if (out->convert_buffer)
7949 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007950 free(out);
7951 *stream_out = NULL;
7952 ALOGD("%s: exit: ret %d", __func__, ret);
7953 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007954}
7955
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307956void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007957 struct audio_stream_out *stream)
7958{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007959 struct stream_out *out = (struct stream_out *)stream;
7960 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007961 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007962
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007963 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307964
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307965 // must deregister from sndmonitor first to prevent races
7966 // between the callback and close_stream
7967 audio_extn_snd_mon_unregister_listener(out);
7968
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007969 /* close adsp hdrl session before standby */
7970 if (out->adsp_hdlr_stream_handle) {
7971 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7972 if (ret)
7973 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7974 out->adsp_hdlr_stream_handle = NULL;
7975 }
7976
Manish Dewangan21a850a2017-08-14 12:03:55 +05307977 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007978 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7979 out->ip_hdlr_handle = NULL;
7980 }
7981
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007982 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307983 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007984 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307985 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307986 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007987 if(ret != 0)
7988 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7989 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007990 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007991 out_standby(&stream->common);
7992
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007993 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007994 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007995 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007996 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007997 if (out->compr_config.codec != NULL)
7998 free(out->compr_config.codec);
7999 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008000
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308001 out->a2dp_compress_mute = false;
8002
Varun Balaraje49253e2017-07-06 19:48:56 +05308003 if (is_interactive_usecase(out->usecase))
8004 free_interactive_usecase(adev, out->usecase);
8005
Ashish Jain83a6cc22016-06-28 14:34:17 +05308006 if (out->convert_buffer != NULL) {
8007 free(out->convert_buffer);
8008 out->convert_buffer = NULL;
8009 }
8010
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008011 if (adev->voice_tx_output == out)
8012 adev->voice_tx_output = NULL;
8013
Aalique Grahame22e49102018-12-18 14:23:57 -08008014 error_log_destroy(out->error_log);
8015 out->error_log = NULL;
8016
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308017 if (adev->primary_output == out)
8018 adev->primary_output = NULL;
8019
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008020 pthread_cond_destroy(&out->cond);
8021 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008022
8023 pthread_mutex_lock(&adev->lock);
8024 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8025 if (out_ctxt != NULL) {
8026 list_remove(&out_ctxt->list);
8027 free(out_ctxt);
8028 } else {
8029 ALOGW("%s, output stream already closed", __func__);
8030 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008031 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008032 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008033 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008034}
8035
8036static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8037{
8038 struct audio_device *adev = (struct audio_device *)dev;
8039 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008040 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008041 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008042 int ret;
8043 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008044 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008045 struct listnode *node;
8046 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008047
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008048 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008049 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008050
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308051 if (!parms)
8052 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308053
Zhou Songd6d71752019-05-21 18:08:51 +08008054 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308055 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8056 if (ret >= 0) {
8057 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008058 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308059 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008060 } else {
8061 ALOGD("sco is off, reset sco and route device to handset/mic");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308062 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008063 audio_extn_sco_reset_configuration();
8064 list_for_each(node, &adev->usecase_list) {
8065 usecase = node_to_item(node, struct audio_usecase, list);
8066 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
8067 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
8068 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
8069 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
8070 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
8071 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
8072 else
8073 continue;
8074 select_devices(adev, usecase->id);
8075 }
8076 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308077 }
8078
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008079 status = voice_set_parameters(adev, parms);
8080 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008081 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008082
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008083 status = platform_set_parameters(adev->platform, parms);
8084 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008085 goto done;
8086
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008087 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8088 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008089 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008090 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8091 adev->bluetooth_nrec = true;
8092 else
8093 adev->bluetooth_nrec = false;
8094 }
8095
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008096 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8097 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008098 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8099 adev->screen_off = false;
8100 else
8101 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008102 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008103 }
8104
Eric Laurent4b084132018-10-19 17:33:43 -07008105 ret = str_parms_get_int(parms, "rotation", &val);
8106 if (ret >= 0) {
8107 bool reverse_speakers = false;
8108 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8109 switch (val) {
8110 // FIXME: note that the code below assumes that the speakers are in the correct placement
8111 // relative to the user when the device is rotated 90deg from its default rotation. This
8112 // assumption is device-specific, not platform-specific like this code.
8113 case 270:
8114 reverse_speakers = true;
8115 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8116 break;
8117 case 0:
8118 case 180:
8119 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8120 break;
8121 case 90:
8122 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8123 break;
8124 default:
8125 ALOGE("%s: unexpected rotation of %d", __func__, val);
8126 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008127 }
Eric Laurent4b084132018-10-19 17:33:43 -07008128 if (status == 0) {
8129 // check and set swap
8130 // - check if orientation changed and speaker active
8131 // - set rotation and cache the rotation value
8132 adev->camera_orientation =
8133 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8134 if (!audio_extn_is_maxx_audio_enabled())
8135 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8136 }
8137 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008138
Mingming Yin514a8bc2014-07-29 15:22:21 -07008139 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8140 if (ret >= 0) {
8141 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8142 adev->bt_wb_speech_enabled = true;
8143 else
8144 adev->bt_wb_speech_enabled = false;
8145 }
8146
Zhou Song12c29502019-03-16 10:37:18 +08008147 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8148 if (ret >= 0) {
8149 val = atoi(value);
8150 adev->swb_speech_mode = val;
8151 }
8152
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008153 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8154 if (ret >= 0) {
8155 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308156 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008157 if (audio_is_output_device(val) &&
8158 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008159 ALOGV("cache new ext disp type and edid");
8160 ret = platform_get_ext_disp_type(adev->platform);
8161 if (ret < 0) {
8162 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308163 } else {
8164 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008165 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308166 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008167 /*
8168 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8169 * Per AudioPolicyManager, USB device is higher priority than WFD.
8170 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8171 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8172 * starting voice call on USB
8173 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008174 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308175 if (ret >= 0)
8176 audio_extn_usb_add_device(device, atoi(value));
8177
Zhou Song6f862822017-11-06 17:27:57 +08008178 if (!audio_extn_usb_is_tunnel_supported()) {
8179 ALOGV("detected USB connect .. disable proxy");
8180 adev->allow_afe_proxy_usage = false;
8181 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008182 }
8183 }
8184
8185 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8186 if (ret >= 0) {
8187 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308188 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008189 /*
8190 * The HDMI / Displayport disconnect handling has been moved to
8191 * audio extension to ensure that its parameters are not
8192 * invalidated prior to updating sysfs of the disconnect event
8193 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8194 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308195 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008196 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308197 if (ret >= 0)
8198 audio_extn_usb_remove_device(device, atoi(value));
8199
Zhou Song6f862822017-11-06 17:27:57 +08008200 if (!audio_extn_usb_is_tunnel_supported()) {
8201 ALOGV("detected USB disconnect .. enable proxy");
8202 adev->allow_afe_proxy_usage = true;
8203 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008204 }
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05308205 if (audio_is_a2dp_out_device(device)) {
8206 struct audio_usecase *usecase;
8207 struct listnode *node;
8208 list_for_each(node, &adev->usecase_list) {
8209 usecase = node_to_item(node, struct audio_usecase, list);
8210 if (PCM_PLAYBACK == usecase->type && usecase->stream.out &&
8211 (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8212 usecase->stream.out->a2dp_compress_mute) {
8213 struct stream_out *out = usecase->stream.out;
8214 ALOGD("Unmuting the stream when Bt-A2dp disconnected and stream is mute");
8215 out->a2dp_compress_mute = false;
8216 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8217 }
8218 }
8219 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008220 }
8221
Aalique Grahame22e49102018-12-18 14:23:57 -08008222 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008223 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008224
8225 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008226 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308227 struct audio_usecase *usecase;
8228 struct listnode *node;
8229 list_for_each(node, &adev->usecase_list) {
8230 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308231 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07008232 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308233 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008234 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308235 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008236 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308237 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308238 ALOGD("Switching to speaker and muting the stream before select_devices");
8239 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308240 //force device switch to re configure encoder
8241 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308242 ALOGD("Unmuting the stream after select_devices");
8243 usecase->stream.out->a2dp_compress_mute = false;
8244 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 +05308245 audio_extn_a2dp_set_handoff_mode(false);
8246 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308247 break;
8248 }
8249 }
8250 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008251
8252 //handle vr audio setparam
8253 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8254 value, sizeof(value));
8255 if (ret >= 0) {
8256 ALOGI("Setting vr mode to be %s", value);
8257 if (!strncmp(value, "true", 4)) {
8258 adev->vr_audio_mode_enabled = true;
8259 ALOGI("Setting vr mode to true");
8260 } else if (!strncmp(value, "false", 5)) {
8261 adev->vr_audio_mode_enabled = false;
8262 ALOGI("Setting vr mode to false");
8263 } else {
8264 ALOGI("wrong vr mode set");
8265 }
8266 }
8267
Eric Laurent4b084132018-10-19 17:33:43 -07008268 //FIXME: to be replaced by proper video capture properties API
8269 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8270 if (ret >= 0) {
8271 int camera_facing = CAMERA_FACING_BACK;
8272 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8273 camera_facing = CAMERA_FACING_FRONT;
8274 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8275 camera_facing = CAMERA_FACING_BACK;
8276 else {
8277 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8278 goto done;
8279 }
8280 adev->camera_orientation =
8281 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8282 struct audio_usecase *usecase;
8283 struct listnode *node;
8284 list_for_each(node, &adev->usecase_list) {
8285 usecase = node_to_item(node, struct audio_usecase, list);
8286 struct stream_in *in = usecase->stream.in;
8287 if (usecase->type == PCM_CAPTURE && in != NULL &&
8288 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8289 select_devices(adev, in->usecase);
8290 }
8291 }
8292 }
8293
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308294 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008295done:
8296 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008297 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308298error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008299 ALOGV("%s: exit with code(%d)", __func__, status);
8300 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008301}
8302
8303static char* adev_get_parameters(const struct audio_hw_device *dev,
8304 const char *keys)
8305{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308306 ALOGD("%s:%s", __func__, keys);
8307
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008308 struct audio_device *adev = (struct audio_device *)dev;
8309 struct str_parms *reply = str_parms_create();
8310 struct str_parms *query = str_parms_create_str(keys);
8311 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308312 char value[256] = {0};
8313 int ret = 0;
8314
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008315 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008316 if (reply) {
8317 str_parms_destroy(reply);
8318 }
8319 if (query) {
8320 str_parms_destroy(query);
8321 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008322 ALOGE("adev_get_parameters: failed to create query or reply");
8323 return NULL;
8324 }
8325
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008326 //handle vr audio getparam
8327
8328 ret = str_parms_get_str(query,
8329 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8330 value, sizeof(value));
8331
8332 if (ret >= 0) {
8333 bool vr_audio_enabled = false;
8334 pthread_mutex_lock(&adev->lock);
8335 vr_audio_enabled = adev->vr_audio_mode_enabled;
8336 pthread_mutex_unlock(&adev->lock);
8337
8338 ALOGI("getting vr mode to %d", vr_audio_enabled);
8339
8340 if (vr_audio_enabled) {
8341 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8342 "true");
8343 goto exit;
8344 } else {
8345 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8346 "false");
8347 goto exit;
8348 }
8349 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008350
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008351 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008352 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008353 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008354 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008355 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308356 pthread_mutex_unlock(&adev->lock);
8357
Naresh Tannirud7205b62014-06-20 02:54:48 +05308358exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008359 str = str_parms_to_str(reply);
8360 str_parms_destroy(query);
8361 str_parms_destroy(reply);
8362
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308363 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008364 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008365}
8366
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008367static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008368{
8369 return 0;
8370}
8371
8372static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8373{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008374 int ret;
8375 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008376
8377 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8378
Haynes Mathew George5191a852013-09-11 14:19:36 -07008379 pthread_mutex_lock(&adev->lock);
8380 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008381 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008382 pthread_mutex_unlock(&adev->lock);
8383 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008384}
8385
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008386static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8387 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008388{
8389 return -ENOSYS;
8390}
8391
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008392static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8393 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008394{
8395 return -ENOSYS;
8396}
8397
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008398static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8399 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008400{
8401 return -ENOSYS;
8402}
8403
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008404static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8405 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008406{
8407 return -ENOSYS;
8408}
8409
8410static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8411{
8412 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008413 struct listnode *node;
8414 struct audio_usecase *usecase = NULL;
8415 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008417 pthread_mutex_lock(&adev->lock);
8418 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008419 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008420 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008421 if (voice_is_in_call(adev) &&
8422 (mode == AUDIO_MODE_NORMAL ||
8423 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008424 list_for_each(node, &adev->usecase_list) {
8425 usecase = node_to_item(node, struct audio_usecase, list);
8426 if (usecase->type == VOICE_CALL)
8427 break;
8428 }
8429 if (usecase &&
8430 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8431 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8432 true);
8433 if (ret != 0) {
8434 /* default service interval was successfully updated,
8435 reopen USB backend with new service interval */
8436 check_usecases_codec_backend(adev,
8437 usecase,
8438 usecase->out_snd_device);
8439 }
8440 }
8441
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008442 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008443 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008444 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008445 // restore device for other active usecases after stop call
8446 list_for_each(node, &adev->usecase_list) {
8447 usecase = node_to_item(node, struct audio_usecase, list);
8448 select_devices(adev, usecase->id);
8449 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008450 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008451 }
8452 pthread_mutex_unlock(&adev->lock);
8453 return 0;
8454}
8455
8456static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8457{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008458 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008459 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008460
8461 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008462 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008463 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008464
Derek Chend2530072014-11-24 12:39:14 -08008465 if (adev->ext_hw_plugin)
8466 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008467
8468 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008469 pthread_mutex_unlock(&adev->lock);
8470
8471 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008472}
8473
8474static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8475{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008476 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008477 return 0;
8478}
8479
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008480static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008481 const struct audio_config *config)
8482{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008483 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008484
Aalique Grahame22e49102018-12-18 14:23:57 -08008485 /* Don't know if USB HIFI in this context so use true to be conservative */
8486 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8487 true /*is_usb_hifi */) != 0)
8488 return 0;
8489
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008490 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8491 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008492}
8493
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008494static bool adev_input_allow_hifi_record(struct audio_device *adev,
8495 audio_devices_t devices,
8496 audio_input_flags_t flags,
8497 audio_source_t source) {
8498 const bool allowed = true;
8499
8500 if (!audio_is_usb_in_device(devices))
8501 return !allowed;
8502
8503 switch (flags) {
8504 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008505 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008506 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8507 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008508 default:
8509 return !allowed;
8510 }
8511
8512 switch (source) {
8513 case AUDIO_SOURCE_DEFAULT:
8514 case AUDIO_SOURCE_MIC:
8515 case AUDIO_SOURCE_UNPROCESSED:
8516 break;
8517 default:
8518 return !allowed;
8519 }
8520
8521 switch (adev->mode) {
8522 case 0:
8523 break;
8524 default:
8525 return !allowed;
8526 }
8527
8528 return allowed;
8529}
8530
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008531static int adev_update_voice_comm_input_stream(struct stream_in *in,
8532 struct audio_config *config)
8533{
8534 bool valid_rate = (config->sample_rate == 8000 ||
8535 config->sample_rate == 16000 ||
8536 config->sample_rate == 32000 ||
8537 config->sample_rate == 48000);
8538 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8539
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008540 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008541 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008542 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8543 in->config = default_pcm_config_voip_copp;
8544 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8545 DEFAULT_VOIP_BUF_DURATION_MS,
8546 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008547 } else {
8548 ALOGW("%s No valid input in voip, use defaults"
8549 "sample rate %u, channel mask 0x%X",
8550 __func__, config->sample_rate, in->channel_mask);
8551 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008552 in->config.rate = config->sample_rate;
8553 in->sample_rate = config->sample_rate;
8554 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008555 //XXX needed for voice_extn_compress_voip_open_input_stream
8556 in->config.rate = config->sample_rate;
8557 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8558 voice_extn_compress_voip_is_active(in->dev)) &&
8559 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8560 valid_rate && valid_ch) {
8561 voice_extn_compress_voip_open_input_stream(in);
8562 // update rate entries to match config from AF
8563 in->config.rate = config->sample_rate;
8564 in->sample_rate = config->sample_rate;
8565 } else {
8566 ALOGW("%s compress voip not active, use defaults", __func__);
8567 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008568 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008569 return 0;
8570}
8571
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008572static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008573 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008574 audio_devices_t devices,
8575 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008576 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308577 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008578 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008579 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008580{
8581 struct audio_device *adev = (struct audio_device *)dev;
8582 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008583 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008584 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008585 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308586 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008587 bool is_usb_dev = audio_is_usb_in_device(devices);
8588 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8589 devices,
8590 flags,
8591 source);
Andy Hung94320602018-10-29 18:31:12 -07008592 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8593 " sample_rate %u, channel_mask %#x, format %#x",
8594 __func__, flags, is_usb_dev, may_use_hifi_record,
8595 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308596
kunleizdff872d2018-08-20 14:40:33 +08008597 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008598 is_usb_dev = false;
8599 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8600 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8601 __func__, devices);
8602 }
8603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008604 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008605
8606 if (!(is_usb_dev && may_use_hifi_record)) {
8607 if (config->sample_rate == 0)
8608 config->sample_rate = 48000;
8609 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8610 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8611 if (config->format == AUDIO_FORMAT_DEFAULT)
8612 config->format = AUDIO_FORMAT_PCM_16_BIT;
8613
8614 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8615
Aalique Grahame22e49102018-12-18 14:23:57 -08008616 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8617 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008618 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308619 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008620
8621 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008622
8623 if (!in) {
8624 ALOGE("failed to allocate input stream");
8625 return -ENOMEM;
8626 }
8627
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308628 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308629 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8630 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008631 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008632 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008633
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008634 in->stream.common.get_sample_rate = in_get_sample_rate;
8635 in->stream.common.set_sample_rate = in_set_sample_rate;
8636 in->stream.common.get_buffer_size = in_get_buffer_size;
8637 in->stream.common.get_channels = in_get_channels;
8638 in->stream.common.get_format = in_get_format;
8639 in->stream.common.set_format = in_set_format;
8640 in->stream.common.standby = in_standby;
8641 in->stream.common.dump = in_dump;
8642 in->stream.common.set_parameters = in_set_parameters;
8643 in->stream.common.get_parameters = in_get_parameters;
8644 in->stream.common.add_audio_effect = in_add_audio_effect;
8645 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8646 in->stream.set_gain = in_set_gain;
8647 in->stream.read = in_read;
8648 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008649 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308650 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008651 in->stream.set_microphone_direction = in_set_microphone_direction;
8652 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008653 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008654
8655 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008656 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008657 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008658 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008659 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008660 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008661 in->bit_width = 16;
8662 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008663 in->direction = MIC_DIRECTION_UNSPECIFIED;
8664 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08008665 list_init(&in->aec_list);
8666 list_init(&in->ns_list);
Haynes Mathew George46740472017-10-27 18:40:12 -07008667
Andy Hung94320602018-10-29 18:31:12 -07008668 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008669 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8670 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8671 /* Force channel config requested to mono if incall
8672 record is being requested for only uplink/downlink */
8673 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8674 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8675 ret = -EINVAL;
8676 goto err_open;
8677 }
8678 }
8679
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008680 if (is_usb_dev && may_use_hifi_record) {
8681 /* HiFi record selects an appropriate format, channel, rate combo
8682 depending on sink capabilities*/
8683 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8684 &config->format,
8685 &in->supported_formats[0],
8686 MAX_SUPPORTED_FORMATS,
8687 &config->channel_mask,
8688 &in->supported_channel_masks[0],
8689 MAX_SUPPORTED_CHANNEL_MASKS,
8690 &config->sample_rate,
8691 &in->supported_sample_rates[0],
8692 MAX_SUPPORTED_SAMPLE_RATES);
8693 if (ret != 0) {
8694 ret = -EINVAL;
8695 goto err_open;
8696 }
8697 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008698 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308699 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308700 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8701 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8702 in->config.format = PCM_FORMAT_S32_LE;
8703 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308704 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8705 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8706 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8707 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8708 bool ret_error = false;
8709 in->bit_width = 24;
8710 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8711 from HAL is 24_packed and 8_24
8712 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8713 24_packed return error indicating supported format is 24_packed
8714 *> In case of any other source requesting 24 bit or float return error
8715 indicating format supported is 16 bit only.
8716
8717 on error flinger will retry with supported format passed
8718 */
8719 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8720 (source != AUDIO_SOURCE_CAMCORDER)) {
8721 config->format = AUDIO_FORMAT_PCM_16_BIT;
8722 if (config->sample_rate > 48000)
8723 config->sample_rate = 48000;
8724 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008725 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8726 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308727 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8728 ret_error = true;
8729 }
8730
8731 if (ret_error) {
8732 ret = -EINVAL;
8733 goto err_open;
8734 }
8735 }
8736
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008737 in->channel_mask = config->channel_mask;
8738 in->format = config->format;
8739
8740 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308741
8742 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8743 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8744 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8745 else {
8746 ret = -EINVAL;
8747 goto err_open;
8748 }
8749 }
8750
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008751 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308752 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
8753 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008754 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8755 is_low_latency = true;
8756#if LOW_LATENCY_CAPTURE_USE_CASE
8757 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8758#endif
8759 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008760 if (!in->realtime) {
8761 in->config = pcm_config_audio_capture;
8762 frame_size = audio_stream_in_frame_size(&in->stream);
8763 buffer_size = get_input_buffer_size(config->sample_rate,
8764 config->format,
8765 channel_count,
8766 is_low_latency);
8767 in->config.period_size = buffer_size / frame_size;
8768 in->config.rate = config->sample_rate;
8769 in->af_period_multiplier = 1;
8770 } else {
8771 // period size is left untouched for rt mode playback
8772 in->config = pcm_config_audio_capture_rt;
8773 in->af_period_multiplier = af_period_multiplier;
8774 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008775 }
8776
8777 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8778 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8779 in->realtime = 0;
8780 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8781 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008782 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008783 in->stream.start = in_start;
8784 in->stream.stop = in_stop;
8785 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8786 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008787 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8788 } else if (in->realtime) {
8789 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008790 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008791 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008792 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008793 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8794 in->config = pcm_config_audio_capture;
8795 frame_size = audio_stream_in_frame_size(&in->stream);
8796 buffer_size = get_input_buffer_size(config->sample_rate,
8797 config->format,
8798 channel_count,
8799 false /*is_low_latency*/);
8800 in->config.period_size = buffer_size / frame_size;
8801 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008802 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008803 switch (config->format) {
8804 case AUDIO_FORMAT_PCM_32_BIT:
8805 in->bit_width = 32;
8806 break;
8807 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8808 case AUDIO_FORMAT_PCM_8_24_BIT:
8809 in->bit_width = 24;
8810 break;
8811 default:
8812 in->bit_width = 16;
8813 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008814 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308815 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008816 if (config->sample_rate == 0)
8817 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8818 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8819 config->sample_rate != 8000) {
8820 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8821 ret = -EINVAL;
8822 goto err_open;
8823 }
8824 if (config->format == AUDIO_FORMAT_DEFAULT)
8825 config->format = AUDIO_FORMAT_PCM_16_BIT;
8826 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8827 config->format = AUDIO_FORMAT_PCM_16_BIT;
8828 ret = -EINVAL;
8829 goto err_open;
8830 }
8831
8832 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8833 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008834 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008835 in->af_period_multiplier = 1;
8836 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8837 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8838 (config->sample_rate == 8000 ||
8839 config->sample_rate == 16000 ||
8840 config->sample_rate == 32000 ||
8841 config->sample_rate == 48000) &&
8842 channel_count == 1) {
8843 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8844 in->config = pcm_config_audio_capture;
8845 frame_size = audio_stream_in_frame_size(&in->stream);
8846 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8847 config->sample_rate,
8848 config->format,
8849 channel_count, false /*is_low_latency*/);
8850 in->config.period_size = buffer_size / frame_size;
8851 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8852 in->config.rate = config->sample_rate;
8853 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008854 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308855 int ret_val;
8856 pthread_mutex_lock(&adev->lock);
8857 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8858 in, config, &channel_mask_updated);
8859 pthread_mutex_unlock(&adev->lock);
8860
8861 if (!ret_val) {
8862 if (channel_mask_updated == true) {
8863 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8864 __func__, config->channel_mask);
8865 ret = -EINVAL;
8866 goto err_open;
8867 }
8868 ALOGD("%s: created multi-channel session succesfully",__func__);
8869 } else if (audio_extn_compr_cap_enabled() &&
8870 audio_extn_compr_cap_format_supported(config->format) &&
8871 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8872 audio_extn_compr_cap_init(in);
8873 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05308874 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308875 if (ret)
8876 goto err_open;
8877 } else {
8878 in->config = pcm_config_audio_capture;
8879 in->config.rate = config->sample_rate;
8880 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308881 in->format = config->format;
8882 frame_size = audio_stream_in_frame_size(&in->stream);
8883 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008884 config->format,
8885 channel_count,
8886 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008887 /* prevent division-by-zero */
8888 if (frame_size == 0) {
8889 ALOGE("%s: Error frame_size==0", __func__);
8890 ret = -EINVAL;
8891 goto err_open;
8892 }
8893
Revathi Uddarajud2634032017-12-07 14:42:34 +05308894 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008895 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008896
Revathi Uddarajud2634032017-12-07 14:42:34 +05308897 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8898 /* optionally use VOIP usecase depending on config(s) */
8899 ret = adev_update_voice_comm_input_stream(in, config);
8900 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008901
Revathi Uddarajud2634032017-12-07 14:42:34 +05308902 if (ret) {
8903 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8904 goto err_open;
8905 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008906 }
Samyak Jainc37062f2019-04-25 18:41:06 +05308907 if (audio_extn_is_concurrent_capture_enabled()) {
8908 /* Acquire lock to avoid two concurrent use cases initialized to
8909 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08008910
Samyak Jainc37062f2019-04-25 18:41:06 +05308911 if (in->usecase == USECASE_AUDIO_RECORD) {
8912 pthread_mutex_lock(&adev->lock);
8913 if (!(adev->pcm_record_uc_state)) {
8914 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8915 adev->pcm_record_uc_state = 1;
8916 pthread_mutex_unlock(&adev->lock);
8917 } else {
8918 pthread_mutex_unlock(&adev->lock);
8919 /* Assign compress record use case for second record */
8920 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8921 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8922 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8923 if (audio_extn_cin_applicable_stream(in)) {
8924 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05308925 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05308926 if (ret)
8927 goto err_open;
8928 }
8929 }
8930 }
kunleiz28c73e72019-03-27 17:24:04 +08008931 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008932 }
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008933
8934 in->config.channels = channel_count;
8935 in->sample_rate = in->config.rate;
8936
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308937 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8938 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008939 devices, flags, in->format,
8940 in->sample_rate, in->bit_width,
8941 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308942 register_format(in->format, in->supported_formats);
8943 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8944 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308945
Aalique Grahame22e49102018-12-18 14:23:57 -08008946 in->error_log = error_log_create(
8947 ERROR_LOG_ENTRIES,
8948 1000000000 /* aggregate consecutive identical errors within one second */);
8949
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008950 /* This stream could be for sound trigger lab,
8951 get sound trigger pcm if present */
8952 audio_extn_sound_trigger_check_and_get_session(in);
8953
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308954 lock_input_stream(in);
8955 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8956 pthread_mutex_lock(&adev->lock);
8957 in->card_status = adev->card_status;
8958 pthread_mutex_unlock(&adev->lock);
8959 pthread_mutex_unlock(&in->lock);
8960
Aalique Grahame22e49102018-12-18 14:23:57 -08008961 stream_app_type_cfg_init(&in->app_type_cfg);
8962
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008963 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008964
8965 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8966 calloc(1, sizeof(streams_input_ctxt_t));
8967 if (in_ctxt == NULL) {
8968 ALOGE("%s fail to allocate input ctxt", __func__);
8969 ret = -ENOMEM;
8970 goto err_open;
8971 }
8972 in_ctxt->input = in;
8973
8974 pthread_mutex_lock(&adev->lock);
8975 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8976 pthread_mutex_unlock(&adev->lock);
8977
Eric Laurent994a6932013-07-17 11:51:42 -07008978 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008979 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008980
8981err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05308982 if (in->usecase == USECASE_AUDIO_RECORD) {
8983 pthread_mutex_lock(&adev->lock);
8984 adev->pcm_record_uc_state = 0;
8985 pthread_mutex_unlock(&adev->lock);
8986 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008987 free(in);
8988 *stream_in = NULL;
8989 return ret;
8990}
8991
8992static void adev_close_input_stream(struct audio_hw_device *dev,
8993 struct audio_stream_in *stream)
8994{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008995 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008996 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008997 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308998
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308999 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009000
kunleiz70e57612018-12-28 17:50:23 +08009001 /* must deregister from sndmonitor first to prevent races
9002 * between the callback and close_stream
9003 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309004 audio_extn_snd_mon_unregister_listener(stream);
9005
kunleiz70e57612018-12-28 17:50:23 +08009006 /* Disable echo reference if there are no active input, hfp call
9007 * and sound trigger while closing input stream
9008 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009009 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009010 !audio_extn_hfp_is_active(adev) &&
9011 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08009012 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08009013 else
9014 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309015
Pallavid7c7a272018-01-16 11:22:55 +05309016 if (in == NULL) {
9017 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9018 return;
9019 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08009020 error_log_destroy(in->error_log);
9021 in->error_log = NULL;
9022
Pallavid7c7a272018-01-16 11:22:55 +05309023
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009024 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309025 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009026 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309027 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009028 if (ret != 0)
9029 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9030 __func__, ret);
9031 } else
9032 in_standby(&stream->common);
9033
Revathi Uddarajud2634032017-12-07 14:42:34 +05309034 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309035 if (in->usecase == USECASE_AUDIO_RECORD) {
9036 adev->pcm_record_uc_state = 0;
9037 }
9038
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009039 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009040 audio_extn_ssr_deinit();
9041 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009042
Garmond Leunge2433c32017-09-28 21:51:22 -07009043 if (audio_extn_ffv_get_stream() == in) {
9044 audio_extn_ffv_stream_deinit();
9045 }
9046
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309047 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009048 audio_extn_compr_cap_format_supported(in->config.format))
9049 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309050
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309051 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05309052 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009053
Mingming Yinfd7607b2016-01-22 12:48:44 -08009054 if (in->is_st_session) {
9055 ALOGV("%s: sound trigger pcm stop lab", __func__);
9056 audio_extn_sound_trigger_stop_lab(in);
9057 }
Derek Chenf939fb72018-11-13 13:34:41 -08009058 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9059 if (in_ctxt != NULL) {
9060 list_remove(&in_ctxt->list);
9061 free(in_ctxt);
9062 } else {
9063 ALOGW("%s, input stream already closed", __func__);
9064 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009065 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309066 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009067 return;
9068}
9069
Aalique Grahame22e49102018-12-18 14:23:57 -08009070/* verifies input and output devices and their capabilities.
9071 *
9072 * This verification is required when enabling extended bit-depth or
9073 * sampling rates, as not all qcom products support it.
9074 *
9075 * Suitable for calling only on initialization such as adev_open().
9076 * It fills the audio_device use_case_table[] array.
9077 *
9078 * Has a side-effect that it needs to configure audio routing / devices
9079 * in order to power up the devices and read the device parameters.
9080 * It does not acquire any hw device lock. Should restore the devices
9081 * back to "normal state" upon completion.
9082 */
9083static int adev_verify_devices(struct audio_device *adev)
9084{
9085 /* enumeration is a bit difficult because one really wants to pull
9086 * the use_case, device id, etc from the hidden pcm_device_table[].
9087 * In this case there are the following use cases and device ids.
9088 *
9089 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9090 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9091 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9092 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9093 * [USECASE_AUDIO_RECORD] = {0, 0},
9094 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9095 * [USECASE_VOICE_CALL] = {2, 2},
9096 *
9097 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9098 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9099 */
9100
9101 /* should be the usecases enabled in adev_open_input_stream() */
9102 static const int test_in_usecases[] = {
9103 USECASE_AUDIO_RECORD,
9104 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9105 };
9106 /* should be the usecases enabled in adev_open_output_stream()*/
9107 static const int test_out_usecases[] = {
9108 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9109 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9110 };
9111 static const usecase_type_t usecase_type_by_dir[] = {
9112 PCM_PLAYBACK,
9113 PCM_CAPTURE,
9114 };
9115 static const unsigned flags_by_dir[] = {
9116 PCM_OUT,
9117 PCM_IN,
9118 };
9119
9120 size_t i;
9121 unsigned dir;
9122 const unsigned card_id = adev->snd_card;
9123
9124 for (dir = 0; dir < 2; ++dir) {
9125 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9126 const unsigned flags_dir = flags_by_dir[dir];
9127 const size_t testsize =
9128 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9129 const int *testcases =
9130 dir ? test_in_usecases : test_out_usecases;
9131 const audio_devices_t audio_device =
9132 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9133
9134 for (i = 0; i < testsize; ++i) {
9135 const audio_usecase_t audio_usecase = testcases[i];
9136 int device_id;
9137 struct pcm_params **pparams;
9138 struct stream_out out;
9139 struct stream_in in;
9140 struct audio_usecase uc_info;
9141 int retval;
9142
9143 pparams = &adev->use_case_table[audio_usecase];
9144 pcm_params_free(*pparams); /* can accept null input */
9145 *pparams = NULL;
9146
9147 /* find the device ID for the use case (signed, for error) */
9148 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9149 if (device_id < 0)
9150 continue;
9151
9152 /* prepare structures for device probing */
9153 memset(&uc_info, 0, sizeof(uc_info));
9154 uc_info.id = audio_usecase;
9155 uc_info.type = usecase_type;
9156 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009157 memset(&in, 0, sizeof(in));
9158 in.device = audio_device;
9159 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9160 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009161 }
9162 memset(&out, 0, sizeof(out));
9163 out.devices = audio_device; /* only field needed in select_devices */
9164 uc_info.stream.out = &out;
9165 uc_info.devices = audio_device;
9166 uc_info.in_snd_device = SND_DEVICE_NONE;
9167 uc_info.out_snd_device = SND_DEVICE_NONE;
9168 list_add_tail(&adev->usecase_list, &uc_info.list);
9169
9170 /* select device - similar to start_(in/out)put_stream() */
9171 retval = select_devices(adev, audio_usecase);
9172 if (retval >= 0) {
9173 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9174#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009175 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009176 if (*pparams) {
9177 ALOGV("%s: (%s) card %d device %d", __func__,
9178 dir ? "input" : "output", card_id, device_id);
9179 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9180 } else {
9181 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9182 }
9183#endif
9184 }
9185
9186 /* deselect device - similar to stop_(in/out)put_stream() */
9187 /* 1. Get and set stream specific mixer controls */
9188 retval = disable_audio_route(adev, &uc_info);
9189 /* 2. Disable the rx device */
9190 retval = disable_snd_device(adev,
9191 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9192 list_remove(&uc_info.list);
9193 }
9194 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009195 return 0;
9196}
9197
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309198int adev_create_audio_patch(struct audio_hw_device *dev,
9199 unsigned int num_sources,
9200 const struct audio_port_config *sources,
9201 unsigned int num_sinks,
9202 const struct audio_port_config *sinks,
9203 audio_patch_handle_t *handle)
9204{
Derek Chenf939fb72018-11-13 13:34:41 -08009205 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309206
Derek Chenf939fb72018-11-13 13:34:41 -08009207 ret = audio_extn_hw_loopback_create_audio_patch(dev,
9208 num_sources,
9209 sources,
9210 num_sinks,
9211 sinks,
9212 handle);
9213 ret |= audio_extn_auto_hal_create_audio_patch(dev,
9214 num_sources,
9215 sources,
9216 num_sinks,
9217 sinks,
9218 handle);
9219 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309220}
9221
9222int adev_release_audio_patch(struct audio_hw_device *dev,
9223 audio_patch_handle_t handle)
9224{
Derek Chenf939fb72018-11-13 13:34:41 -08009225 int ret;
9226
9227 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
9228 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
9229 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309230}
9231
9232int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9233{
Derek Chenf13dd492018-11-13 14:53:51 -08009234 int ret = 0;
9235
9236 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9237 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9238 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309239}
9240
9241int adev_set_audio_port_config(struct audio_hw_device *dev,
9242 const struct audio_port_config *config)
9243{
Derek Chenf13dd492018-11-13 14:53:51 -08009244 int ret = 0;
9245
9246 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9247 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9248 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309249}
9250
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009251static int adev_dump(const audio_hw_device_t *device __unused,
9252 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009253{
9254 return 0;
9255}
9256
9257static int adev_close(hw_device_t *device)
9258{
Aalique Grahame22e49102018-12-18 14:23:57 -08009259 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309260 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009261
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309262 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009263 return 0;
9264
9265 pthread_mutex_lock(&adev_init_lock);
9266
9267 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309268 if (audio_extn_spkr_prot_is_enabled())
9269 audio_extn_spkr_prot_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309270 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009271 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009272 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009273 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009274 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309275 audio_extn_utils_release_streams_cfg_lists(
9276 &adev->streams_output_cfg_list,
9277 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309278 if (audio_extn_qap_is_enabled())
9279 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309280 if (audio_extn_qaf_is_enabled())
9281 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009282 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009283 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009284 free(adev->snd_dev_ref_cnt);
9285 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009286 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9287 pcm_params_free(adev->use_case_table[i]);
9288 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009289 if (adev->adm_deinit)
9290 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309291 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009292 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309293 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309294 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009295 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309296 if (adev->device_cfg_params) {
9297 free(adev->device_cfg_params);
9298 adev->device_cfg_params = NULL;
9299 }
Derek Chend2530072014-11-24 12:39:14 -08009300 if(adev->ext_hw_plugin)
9301 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009302 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009303 free(device);
9304 adev = NULL;
9305 }
9306 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309307 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009308 return 0;
9309}
9310
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009311/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9312 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9313 * just that it _might_ work.
9314 */
9315static int period_size_is_plausible_for_low_latency(int period_size)
9316{
9317 switch (period_size) {
9318 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009319 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009320 case 240:
9321 case 320:
9322 case 480:
9323 return 1;
9324 default:
9325 return 0;
9326 }
9327}
9328
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309329static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9330{
9331 bool is_snd_card_status = false;
9332 bool is_ext_device_status = false;
9333 char value[32];
9334 int card = -1;
9335 card_status_t status;
9336
9337 if (cookie != adev || !parms)
9338 return;
9339
9340 if (!parse_snd_card_status(parms, &card, &status)) {
9341 is_snd_card_status = true;
9342 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9343 is_ext_device_status = true;
9344 } else {
9345 // not a valid event
9346 return;
9347 }
9348
9349 pthread_mutex_lock(&adev->lock);
9350 if (card == adev->snd_card || is_ext_device_status) {
9351 if (is_snd_card_status && adev->card_status != status) {
9352 adev->card_status = status;
9353 platform_snd_card_update(adev->platform, status);
9354 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -08009355 audio_extn_auto_hal_set_parameters(adev, parms);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309356 } else if (is_ext_device_status) {
9357 platform_set_parameters(adev->platform, parms);
9358 }
9359 }
9360 pthread_mutex_unlock(&adev->lock);
9361 return;
9362}
9363
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309364/* out and adev lock held */
9365static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9366{
9367 struct audio_usecase *uc_info;
9368 float left_p;
9369 float right_p;
9370 audio_devices_t devices;
9371
9372 uc_info = get_usecase_from_list(adev, out->usecase);
9373 if (uc_info == NULL) {
9374 ALOGE("%s: Could not find the usecase (%d) in the list",
9375 __func__, out->usecase);
9376 return -EINVAL;
9377 }
9378
9379 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9380 out->usecase, use_case_table[out->usecase]);
9381
9382 if (restore) {
9383 // restore A2DP device for active usecases and unmute if required
9384 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9385 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9386 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9387 select_devices(adev, uc_info->id);
9388 pthread_mutex_lock(&out->compr_mute_lock);
9389 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05309390 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309391 out->a2dp_compress_mute = false;
9392 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9393 }
9394 pthread_mutex_unlock(&out->compr_mute_lock);
9395 }
9396 } else {
9397 // mute compress stream if suspended
9398 pthread_mutex_lock(&out->compr_mute_lock);
9399 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9400 (!out->a2dp_compress_mute)) {
9401 if (!out->standby) {
9402 ALOGD("%s: selecting speaker and muting stream", __func__);
9403 devices = out->devices;
9404 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9405 left_p = out->volume_l;
9406 right_p = out->volume_r;
9407 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9408 compress_pause(out->compr);
9409 out_set_compr_volume(&out->stream, (float)0, (float)0);
9410 out->a2dp_compress_mute = true;
9411 select_devices(adev, out->usecase);
9412 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9413 compress_resume(out->compr);
9414 out->devices = devices;
9415 out->volume_l = left_p;
9416 out->volume_r = right_p;
9417 }
9418 }
9419 pthread_mutex_unlock(&out->compr_mute_lock);
9420 }
9421 ALOGV("%s: exit", __func__);
9422 return 0;
9423}
9424
9425int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9426{
9427 int ret = 0;
9428
9429 lock_output_stream(out);
9430 pthread_mutex_lock(&adev->lock);
9431
9432 ret = check_a2dp_restore_l(adev, out, restore);
9433
9434 pthread_mutex_unlock(&adev->lock);
9435 pthread_mutex_unlock(&out->lock);
9436 return ret;
9437}
9438
Haynes Mathew George01156f92018-04-13 15:29:54 -07009439void adev_on_battery_status_changed(bool charging)
9440{
9441 pthread_mutex_lock(&adev->lock);
9442 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9443 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009444 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009445 pthread_mutex_unlock(&adev->lock);
9446}
9447
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009448static int adev_open(const hw_module_t *module, const char *name,
9449 hw_device_t **device)
9450{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309451 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009452 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309453 char mixer_ctl_name[128] = {0};
9454 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309455
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009456 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009457 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9458
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009459 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009460 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009461 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009462 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009463 ALOGD("%s: returning existing instance of adev", __func__);
9464 ALOGD("%s: exit", __func__);
9465 pthread_mutex_unlock(&adev_init_lock);
9466 return 0;
9467 }
9468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009469 adev = calloc(1, sizeof(struct audio_device));
9470
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009471 if (!adev) {
9472 pthread_mutex_unlock(&adev_init_lock);
9473 return -ENOMEM;
9474 }
9475
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009476 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9477
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009478 // register audio ext hidl at the earliest
9479 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309480#ifdef DYNAMIC_LOG_ENABLED
9481 register_for_dynamic_logging("hal");
9482#endif
9483
Derek Chenf939fb72018-11-13 13:34:41 -08009484 /* default audio HAL major version */
9485 uint32_t maj_version = 2;
9486 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9487 maj_version = atoi(value);
9488
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009489 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009490 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009491 adev->device.common.module = (struct hw_module_t *)module;
9492 adev->device.common.close = adev_close;
9493
9494 adev->device.init_check = adev_init_check;
9495 adev->device.set_voice_volume = adev_set_voice_volume;
9496 adev->device.set_master_volume = adev_set_master_volume;
9497 adev->device.get_master_volume = adev_get_master_volume;
9498 adev->device.set_master_mute = adev_set_master_mute;
9499 adev->device.get_master_mute = adev_get_master_mute;
9500 adev->device.set_mode = adev_set_mode;
9501 adev->device.set_mic_mute = adev_set_mic_mute;
9502 adev->device.get_mic_mute = adev_get_mic_mute;
9503 adev->device.set_parameters = adev_set_parameters;
9504 adev->device.get_parameters = adev_get_parameters;
9505 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9506 adev->device.open_output_stream = adev_open_output_stream;
9507 adev->device.close_output_stream = adev_close_output_stream;
9508 adev->device.open_input_stream = adev_open_input_stream;
9509 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309510 adev->device.create_audio_patch = adev_create_audio_patch;
9511 adev->device.release_audio_patch = adev_release_audio_patch;
9512 adev->device.get_audio_port = adev_get_audio_port;
9513 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009514 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309515 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009516
9517 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009518 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009519 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009520 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009521 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009522 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009523 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309524 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009525 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009526 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009527 /* Init audio and voice feature */
9528 audio_extn_feature_init();
9529 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009530 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009531 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009532 list_init(&adev->active_inputs_list);
9533 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009534 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009535 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309536 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309537 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309538 adev->perf_lock_opts[0] = 0x101;
9539 adev->perf_lock_opts[1] = 0x20E;
9540 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009541 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009542 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309543 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009544 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009546 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009547 adev->platform = platform_init(adev);
9548 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009549 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009550 free(adev->snd_dev_ref_cnt);
9551 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009552 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009553 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9554 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009555 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009556 return -EINVAL;
9557 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009558
Aalique Grahame22e49102018-12-18 14:23:57 -08009559 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309560 if (audio_extn_qap_is_enabled()) {
9561 ret = audio_extn_qap_init(adev);
9562 if (ret < 0) {
9563 pthread_mutex_destroy(&adev->lock);
9564 free(adev);
9565 adev = NULL;
9566 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9567 *device = NULL;
9568 pthread_mutex_unlock(&adev_init_lock);
9569 return ret;
9570 }
9571 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
9572 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
9573 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009574
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309575 if (audio_extn_qaf_is_enabled()) {
9576 ret = audio_extn_qaf_init(adev);
9577 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009578 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309579 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009580 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309581 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9582 *device = NULL;
9583 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309584 return ret;
9585 }
9586
9587 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9588 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9589 }
9590
Derek Chenae7b0342019-02-08 15:17:04 -08009591 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009592 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9593
Eric Laurentc4aef752013-09-12 17:45:53 -07009594 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9595 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9596 if (adev->visualizer_lib == NULL) {
9597 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9598 } else {
9599 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9600 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009601 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009602 "visualizer_hal_start_output");
9603 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009604 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009605 "visualizer_hal_stop_output");
9606 }
9607 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309608 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009609 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009610 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009611 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309612 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009613 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009614
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009615 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9616 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9617 if (adev->offload_effects_lib == NULL) {
9618 ALOGE("%s: DLOPEN failed for %s", __func__,
9619 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9620 } else {
9621 ALOGV("%s: DLOPEN successful for %s", __func__,
9622 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9623 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309624 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009625 "offload_effects_bundle_hal_start_output");
9626 adev->offload_effects_stop_output =
9627 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9628 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009629 adev->offload_effects_set_hpx_state =
9630 (int (*)(bool))dlsym(adev->offload_effects_lib,
9631 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309632 adev->offload_effects_get_parameters =
9633 (void (*)(struct str_parms *, struct str_parms *))
9634 dlsym(adev->offload_effects_lib,
9635 "offload_effects_bundle_get_parameters");
9636 adev->offload_effects_set_parameters =
9637 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9638 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009639 }
9640 }
9641
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009642 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9643 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9644 if (adev->adm_lib == NULL) {
9645 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9646 } else {
9647 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9648 adev->adm_init = (adm_init_t)
9649 dlsym(adev->adm_lib, "adm_init");
9650 adev->adm_deinit = (adm_deinit_t)
9651 dlsym(adev->adm_lib, "adm_deinit");
9652 adev->adm_register_input_stream = (adm_register_input_stream_t)
9653 dlsym(adev->adm_lib, "adm_register_input_stream");
9654 adev->adm_register_output_stream = (adm_register_output_stream_t)
9655 dlsym(adev->adm_lib, "adm_register_output_stream");
9656 adev->adm_deregister_stream = (adm_deregister_stream_t)
9657 dlsym(adev->adm_lib, "adm_deregister_stream");
9658 adev->adm_request_focus = (adm_request_focus_t)
9659 dlsym(adev->adm_lib, "adm_request_focus");
9660 adev->adm_abandon_focus = (adm_abandon_focus_t)
9661 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009662 adev->adm_set_config = (adm_set_config_t)
9663 dlsym(adev->adm_lib, "adm_set_config");
9664 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9665 dlsym(adev->adm_lib, "adm_request_focus_v2");
9666 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9667 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9668 adev->adm_on_routing_change = (adm_on_routing_change_t)
9669 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009670 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9671 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009672 }
9673 }
9674
Aalique Grahame22e49102018-12-18 14:23:57 -08009675 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009676 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009677 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009678 //initialize this to false for now,
9679 //this will be set to true through set param
9680 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009681
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009682 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009683 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009684
9685 if (k_enable_extended_precision)
9686 adev_verify_devices(adev);
9687
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009688 adev->dsp_bit_width_enforce_mode =
9689 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009690
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309691 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9692 &adev->streams_output_cfg_list,
9693 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009694
Kiran Kandi910e1862013-10-29 13:29:42 -07009695 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009696
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009697 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009698 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9699 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009700 trial = atoi(value);
9701 if (period_size_is_plausible_for_low_latency(trial)) {
9702 pcm_config_low_latency.period_size = trial;
9703 pcm_config_low_latency.start_threshold = trial / 4;
9704 pcm_config_low_latency.avail_min = trial / 4;
9705 configured_low_latency_capture_period_size = trial;
9706 }
9707 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009708 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9709 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009710 trial = atoi(value);
9711 if (period_size_is_plausible_for_low_latency(trial)) {
9712 configured_low_latency_capture_period_size = trial;
9713 }
9714 }
9715
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009716 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9717
Eric Laurent4b084132018-10-19 17:33:43 -07009718 adev->camera_orientation = CAMERA_DEFAULT;
9719
Aalique Grahame22e49102018-12-18 14:23:57 -08009720 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9721 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009722 af_period_multiplier = atoi(value);
9723 if (af_period_multiplier < 0)
9724 af_period_multiplier = 2;
9725 else if (af_period_multiplier > 4)
9726 af_period_multiplier = 4;
9727
9728 ALOGV("new period_multiplier = %d", af_period_multiplier);
9729 }
9730
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009731 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009732
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009733 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009734 pthread_mutex_unlock(&adev_init_lock);
9735
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009736 if (adev->adm_init)
9737 adev->adm_data = adev->adm_init();
9738
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309739 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309740 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009741 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309742
9743 audio_extn_snd_mon_init();
9744 pthread_mutex_lock(&adev->lock);
9745 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9746 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009747 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9748 /*
9749 * if the battery state callback happens before charging can be queried,
9750 * it will be guarded with the adev->lock held in the cb function and so
9751 * the callback value will reflect the latest state
9752 */
9753 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309754 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009755 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009756 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009757 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309758 /* Allocate memory for Device config params */
9759 adev->device_cfg_params = (struct audio_device_config_param*)
9760 calloc(platform_get_max_codec_backend(),
9761 sizeof(struct audio_device_config_param));
9762 if (adev->device_cfg_params == NULL)
9763 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309764
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309765 /*
9766 * Check if new PSPD matrix mixer control is supported. If not
9767 * supported, then set flag so that old mixer ctrl is sent while
9768 * sending pspd coefficients on older kernel version. Query mixer
9769 * control for default pcm id and channel value one.
9770 */
9771 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9772 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9773
9774 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9775 if (!ctl) {
9776 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9777 __func__, mixer_ctl_name);
9778 adev->use_old_pspd_mix_ctrl = true;
9779 }
9780
Eric Laurent994a6932013-07-17 11:51:42 -07009781 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009782 return 0;
9783}
9784
9785static struct hw_module_methods_t hal_module_methods = {
9786 .open = adev_open,
9787};
9788
9789struct audio_module HAL_MODULE_INFO_SYM = {
9790 .common = {
9791 .tag = HARDWARE_MODULE_TAG,
9792 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9793 .hal_api_version = HARDWARE_HAL_API_VERSION,
9794 .id = AUDIO_HARDWARE_MODULE_ID,
9795 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009796 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009797 .methods = &hal_module_methods,
9798 },
9799};