blob: 7a2c2b95a21813fcf04af6a3d424823c1872fd17 [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",
Rahul Sharma99770982019-03-06 17:05:26 +0530409 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700410};
411
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700412static const audio_usecase_t offload_usecases[] = {
413 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700414 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
415 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
416 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
417 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
418 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
419 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700422};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800423
Varun Balaraje49253e2017-07-06 19:48:56 +0530424static const audio_usecase_t interactive_usecases[] = {
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
426 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
427 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
428 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
429 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
433};
434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800435#define STRING_TO_ENUM(string) { #string, string }
436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437struct string_to_enum {
438 const char *name;
439 uint32_t value;
440};
441
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700442static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800444 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
445 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
446 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700447 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700451 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
452 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
453 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
455 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
456 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
457 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
458 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800462};
463
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700464static const struct string_to_enum formats_name_to_enum_table[] = {
465 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
466 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
467 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700468 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
469 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
470 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700471 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800472 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
473 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700474 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800475};
476
477//list of all supported sample rates by HDMI specification.
478static const int out_hdmi_sample_rates[] = {
479 32000, 44100, 48000, 88200, 96000, 176400, 192000,
480};
481
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700482static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800483 STRING_TO_ENUM(32000),
484 STRING_TO_ENUM(44100),
485 STRING_TO_ENUM(48000),
486 STRING_TO_ENUM(88200),
487 STRING_TO_ENUM(96000),
488 STRING_TO_ENUM(176400),
489 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700490};
491
Carter Hsu2e429db2019-05-14 18:50:52 +0800492struct in_effect_list {
493 struct listnode list;
494 effect_handle_t handle;
495};
496
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700497static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700498static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700499static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700500//cache last MBDRC cal step level
501static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700502
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530503static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
504static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700505static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800506static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530507static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530508
Derek Chen6f293672019-04-01 01:40:24 -0700509static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
510static void in_snd_mon_cb(void * stream, struct str_parms * parms);
511static void out_snd_mon_cb(void * stream, struct str_parms * parms);
512
Zhou Song4721e282019-08-26 14:16:12 +0800513static int configure_btsco_sample_rate(snd_device_t snd_device);
514
Vatsal Buchac09ae062018-11-14 13:25:08 +0530515#ifdef AUDIO_FEATURE_ENABLED_GCOV
516extern void __gcov_flush();
517static void enable_gcov()
518{
519 __gcov_flush();
520}
521#else
522static void enable_gcov()
523{
524}
525#endif
526
justinweng20fb6d82019-02-21 18:49:00 -0700527static int in_set_microphone_direction(const struct audio_stream_in *stream,
528 audio_microphone_direction_t dir);
529static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
530
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700531static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
532 int flags __unused)
533{
534 int dir = 0;
535 switch (uc_id) {
536 case USECASE_AUDIO_RECORD_LOW_LATENCY:
537 dir = 1;
538 case USECASE_AUDIO_PLAYBACK_ULL:
539 break;
540 default:
541 return false;
542 }
543
544 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
545 PCM_PLAYBACK : PCM_CAPTURE);
546 if (adev->adm_is_noirq_avail)
547 return adev->adm_is_noirq_avail(adev->adm_data,
548 adev->snd_card, dev_id, dir);
549 return false;
550}
551
552static void register_out_stream(struct stream_out *out)
553{
554 struct audio_device *adev = out->dev;
555 if (is_offload_usecase(out->usecase) ||
556 !adev->adm_register_output_stream)
557 return;
558
559 // register stream first for backward compatibility
560 adev->adm_register_output_stream(adev->adm_data,
561 out->handle,
562 out->flags);
563
564 if (!adev->adm_set_config)
565 return;
566
567 if (out->realtime)
568 adev->adm_set_config(adev->adm_data,
569 out->handle,
570 out->pcm, &out->config);
571}
572
573static void register_in_stream(struct stream_in *in)
574{
575 struct audio_device *adev = in->dev;
576 if (!adev->adm_register_input_stream)
577 return;
578
579 adev->adm_register_input_stream(adev->adm_data,
580 in->capture_handle,
581 in->flags);
582
583 if (!adev->adm_set_config)
584 return;
585
586 if (in->realtime)
587 adev->adm_set_config(adev->adm_data,
588 in->capture_handle,
589 in->pcm,
590 &in->config);
591}
592
593static void request_out_focus(struct stream_out *out, long ns)
594{
595 struct audio_device *adev = out->dev;
596
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700597 if (adev->adm_request_focus_v2)
598 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
599 else if (adev->adm_request_focus)
600 adev->adm_request_focus(adev->adm_data, out->handle);
601}
602
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700603static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700604{
605 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700606 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700607
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700608 if (adev->adm_request_focus_v2_1)
609 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
610 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700611 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
612 else if (adev->adm_request_focus)
613 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700614
615 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700616}
617
618static void release_out_focus(struct stream_out *out)
619{
620 struct audio_device *adev = out->dev;
621
622 if (adev->adm_abandon_focus)
623 adev->adm_abandon_focus(adev->adm_data, out->handle);
624}
625
626static void release_in_focus(struct stream_in *in)
627{
628 struct audio_device *adev = in->dev;
629 if (adev->adm_abandon_focus)
630 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
631}
632
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530633static int parse_snd_card_status(struct str_parms *parms, int *card,
634 card_status_t *status)
635{
636 char value[32]={0};
637 char state[32]={0};
638
639 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
640 if (ret < 0)
641 return -1;
642
643 // sscanf should be okay as value is of max length 32.
644 // same as sizeof state.
645 if (sscanf(value, "%d,%s", card, state) < 2)
646 return -1;
647
648 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
649 CARD_STATUS_OFFLINE;
650 return 0;
651}
652
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700653static inline void adjust_frames_for_device_delay(struct stream_out *out,
654 uint32_t *dsp_frames) {
655 // Adjustment accounts for A2dp encoder latency with offload usecases
656 // Note: Encoder latency is returned in ms.
657 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
658 unsigned long offset =
659 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
660 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
661 }
662}
663
vivek mehtaa76401a2015-04-24 14:12:15 -0700664__attribute__ ((visibility ("default")))
665bool audio_hw_send_gain_dep_calibration(int level) {
666 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700667 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700668
669 pthread_mutex_lock(&adev_init_lock);
670
671 if (adev != NULL && adev->platform != NULL) {
672 pthread_mutex_lock(&adev->lock);
673 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700674
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530675 // cache level info for any of the use case which
676 // was not started.
677 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700678
vivek mehtaa76401a2015-04-24 14:12:15 -0700679 pthread_mutex_unlock(&adev->lock);
680 } else {
681 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
682 }
683
684 pthread_mutex_unlock(&adev_init_lock);
685
686 return ret_val;
687}
688
Ashish Jain5106d362016-05-11 19:23:33 +0530689static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
690{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800691 bool gapless_enabled = false;
692 const char *mixer_ctl_name = "Compress Gapless Playback";
693 struct mixer_ctl *ctl;
694
695 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700696 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530697
698 /*Disable gapless if its AV playback*/
699 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800700
701 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
702 if (!ctl) {
703 ALOGE("%s: Could not get ctl for mixer cmd - %s",
704 __func__, mixer_ctl_name);
705 return -EINVAL;
706 }
707
708 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
709 ALOGE("%s: Could not set gapless mode %d",
710 __func__, gapless_enabled);
711 return -EINVAL;
712 }
713 return 0;
714}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700715
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700716__attribute__ ((visibility ("default")))
717int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
718 int table_size) {
719 int ret_val = 0;
720 ALOGV("%s: enter ... ", __func__);
721
722 pthread_mutex_lock(&adev_init_lock);
723 if (adev == NULL) {
724 ALOGW("%s: adev is NULL .... ", __func__);
725 goto done;
726 }
727
728 pthread_mutex_lock(&adev->lock);
729 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
730 pthread_mutex_unlock(&adev->lock);
731done:
732 pthread_mutex_unlock(&adev_init_lock);
733 ALOGV("%s: exit ... ", __func__);
734 return ret_val;
735}
736
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800737bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800738{
739 bool ret = false;
740 ALOGV("%s: enter ...", __func__);
741
742 pthread_mutex_lock(&adev_init_lock);
743
744 if (adev != NULL && adev->platform != NULL) {
745 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800746 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800747 pthread_mutex_unlock(&adev->lock);
748 }
749
750 pthread_mutex_unlock(&adev_init_lock);
751
752 ALOGV("%s: exit with ret %d", __func__, ret);
753 return ret;
754}
Aalique Grahame22e49102018-12-18 14:23:57 -0800755
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700756static bool is_supported_format(audio_format_t format)
757{
Eric Laurent86e17132013-09-12 17:49:30 -0700758 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530759 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530760 format == AUDIO_FORMAT_AAC_LC ||
761 format == AUDIO_FORMAT_AAC_HE_V1 ||
762 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530763 format == AUDIO_FORMAT_AAC_ADTS_LC ||
764 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
765 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530766 format == AUDIO_FORMAT_AAC_LATM_LC ||
767 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
768 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530769 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
770 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530771 format == AUDIO_FORMAT_PCM_FLOAT ||
772 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700773 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530774 format == AUDIO_FORMAT_AC3 ||
775 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700776 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530777 format == AUDIO_FORMAT_DTS ||
778 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800779 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530780 format == AUDIO_FORMAT_ALAC ||
781 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530782 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530783 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800784 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530785 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700786 format == AUDIO_FORMAT_APTX ||
787 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800788 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700789
790 return false;
791}
792
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700793static inline bool is_mmap_usecase(audio_usecase_t uc_id)
794{
795 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
796 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
797}
798
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700799static inline bool is_valid_volume(float left, float right)
800{
801 return ((left >= 0.0f && right >= 0.0f) ? true : false);
802}
803
Avinash Vaish71a8b972014-07-24 15:36:33 +0530804static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
805 struct audio_usecase *uc_info)
806{
807 struct listnode *node;
808 struct audio_usecase *usecase;
809
810 if (uc_info == NULL)
811 return -EINVAL;
812
813 /* Re-route all voice usecases on the shared backend other than the
814 specified usecase to new snd devices */
815 list_for_each(node, &adev->usecase_list) {
816 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800817 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530818 enable_audio_route(adev, usecase);
819 }
820 return 0;
821}
822
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530823static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530824{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530825 ALOGV("%s", __func__);
826 audio_route_apply_and_update_path(adev->audio_route,
827 "asrc-mode");
828 adev->asrc_mode_enabled = true;
829}
830
831static void disable_asrc_mode(struct audio_device *adev)
832{
833 ALOGV("%s", __func__);
834 audio_route_reset_and_update_path(adev->audio_route,
835 "asrc-mode");
836 adev->asrc_mode_enabled = false;
837}
838
839/*
840 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
841 * 44.1 or Native DSD backends are enabled for any of current use case.
842 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
843 * - Disable current mix path use case(Headphone backend) and re-enable it with
844 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
845 * e.g. Naitve DSD or Headphone 44.1 -> + 48
846 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530847static void check_and_set_asrc_mode(struct audio_device *adev,
848 struct audio_usecase *uc_info,
849 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530850{
851 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530852 int i, num_new_devices = 0;
853 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
854 /*
855 *Split snd device for new combo use case
856 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
857 */
858 if (platform_split_snd_device(adev->platform,
859 snd_device,
860 &num_new_devices,
861 split_new_snd_devices) == 0) {
862 for (i = 0; i < num_new_devices; i++)
863 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
864 } else {
865 int new_backend_idx = platform_get_backend_index(snd_device);
866 if (((new_backend_idx == HEADPHONE_BACKEND) ||
867 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
868 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
869 !adev->asrc_mode_enabled) {
870 struct listnode *node = NULL;
871 struct audio_usecase *uc = NULL;
872 struct stream_out *curr_out = NULL;
873 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
874 int i, num_devices, ret = 0;
875 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530876
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530877 list_for_each(node, &adev->usecase_list) {
878 uc = node_to_item(node, struct audio_usecase, list);
879 curr_out = (struct stream_out*) uc->stream.out;
880 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
881 /*
882 *Split snd device for existing combo use case
883 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
884 */
885 ret = platform_split_snd_device(adev->platform,
886 uc->out_snd_device,
887 &num_devices,
888 split_snd_devices);
889 if (ret < 0 || num_devices == 0) {
890 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
891 split_snd_devices[0] = uc->out_snd_device;
892 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800893 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530894 for (i = 0; i < num_devices; i++) {
895 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
896 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
897 if((new_backend_idx == HEADPHONE_BACKEND) &&
898 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
899 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
900 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
901 __func__);
902 enable_asrc_mode(adev);
903 break;
904 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
905 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
906 (usecase_backend_idx == HEADPHONE_BACKEND)) {
907 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
908 __func__);
909 disable_audio_route(adev, uc);
910 disable_snd_device(adev, uc->out_snd_device);
911 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
912 if (new_backend_idx == DSD_NATIVE_BACKEND)
913 audio_route_apply_and_update_path(adev->audio_route,
914 "hph-true-highquality-mode");
915 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
916 (curr_out->bit_width >= 24))
917 audio_route_apply_and_update_path(adev->audio_route,
918 "hph-highquality-mode");
919 enable_asrc_mode(adev);
920 enable_snd_device(adev, uc->out_snd_device);
921 enable_audio_route(adev, uc);
922 break;
923 }
924 }
925 // reset split devices count
926 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800927 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530928 if (adev->asrc_mode_enabled)
929 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530930 }
931 }
932 }
933}
934
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700935static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
936 struct audio_effect_config effect_config,
937 unsigned int param_value)
938{
939 char mixer_ctl_name[] = "Audio Effect";
940 struct mixer_ctl *ctl;
941 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800942 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700943
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700944 if (in == NULL) {
945 ALOGE("%s: active input stream is NULL", __func__);
946 return -EINVAL;
947 }
948
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700949 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
950 if (!ctl) {
951 ALOGE("%s: Could not get mixer ctl - %s",
952 __func__, mixer_ctl_name);
953 return -EINVAL;
954 }
955
956 set_values[0] = 1; //0:Rx 1:Tx
957 set_values[1] = in->app_type_cfg.app_type;
958 set_values[2] = (long)effect_config.module_id;
959 set_values[3] = (long)effect_config.instance_id;
960 set_values[4] = (long)effect_config.param_id;
961 set_values[5] = param_value;
962
963 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
964
965 return 0;
966
967}
968
969static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
970 int effect_type, unsigned int *param_value)
971{
972 int ret = 0;
973 struct audio_effect_config other_effect_config;
974 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800975 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700976
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700977 if (in == NULL) {
978 ALOGE("%s: active input stream is NULL", __func__);
979 return -EINVAL;
980 }
981
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700982 usecase = get_usecase_from_list(adev, in->usecase);
983 if (!usecase)
984 return -EINVAL;
985
986 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
987 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
988 if (ret < 0) {
989 ALOGE("%s Failed to get effect params %d", __func__, ret);
990 return ret;
991 }
992
993 if (module_id == other_effect_config.module_id) {
994 //Same module id for AEC/NS. Values need to be combined
995 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
996 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
997 *param_value |= other_effect_config.param_value;
998 }
999 }
1000
1001 return ret;
1002}
1003
1004static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301005{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001006 struct audio_effect_config effect_config;
1007 struct audio_usecase *usecase = NULL;
1008 int ret = 0;
1009 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001010 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001011
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001012 if(!voice_extn_is_dynamic_ecns_enabled())
1013 return ENOSYS;
1014
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001015 if (!in) {
1016 ALOGE("%s: Invalid input stream", __func__);
1017 return -EINVAL;
1018 }
1019
1020 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1021
1022 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001023 if (usecase == NULL) {
1024 ALOGE("%s: Could not find the usecase (%d) in the list",
1025 __func__, in->usecase);
1026 return -EINVAL;
1027 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001028
1029 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1030 if (ret < 0) {
1031 ALOGE("%s Failed to get module id %d", __func__, ret);
1032 return ret;
1033 }
1034 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1035 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1036
1037 if(enable)
1038 param_value = effect_config.param_value;
1039
1040 /*Special handling for AEC & NS effects Param values need to be
1041 updated if module ids are same*/
1042
1043 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1044 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1045 if (ret < 0)
1046 return ret;
1047 }
1048
1049 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1050
1051 return ret;
1052}
1053
1054static void check_and_enable_effect(struct audio_device *adev)
1055{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001056 if(!voice_extn_is_dynamic_ecns_enabled())
1057 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001058
Eric Laurent637e2d42018-11-15 12:24:31 -08001059 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001060
Eric Laurent637e2d42018-11-15 12:24:31 -08001061 if (in != NULL && !in->standby) {
1062 if (in->enable_aec)
1063 enable_disable_effect(adev, EFFECT_AEC, true);
1064
1065 if (in->enable_ns &&
1066 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1067 enable_disable_effect(adev, EFFECT_NS, true);
1068 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001069 }
1070}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001071
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001072int pcm_ioctl(struct pcm *pcm, int request, ...)
1073{
1074 va_list ap;
1075 void * arg;
1076 int pcm_fd = *(int*)pcm;
1077
1078 va_start(ap, request);
1079 arg = va_arg(ap, void *);
1080 va_end(ap);
1081
1082 return ioctl(pcm_fd, request, arg);
1083}
1084
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001085int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001086 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001087{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001089 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301090 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301091 struct stream_in *in = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301092 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001093
1094 if (usecase == NULL)
1095 return -EINVAL;
1096
1097 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1098
Carter Hsu2e429db2019-05-14 18:50:52 +08001099 if (usecase->type == PCM_CAPTURE) {
1100 struct stream_in *in = usecase->stream.in;
1101 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001103
1104 if (in) {
1105 if (in->enable_aec || in->enable_ec_port) {
1106 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
1107 struct listnode *node;
1108 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1109 USECASE_AUDIO_PLAYBACK_VOIP);
1110 if (voip_usecase) {
1111 out_device = voip_usecase->stream.out->devices;
1112 } else if (adev->primary_output &&
1113 !adev->primary_output->standby) {
1114 out_device = adev->primary_output->devices;
1115 } else {
1116 list_for_each(node, &adev->usecase_list) {
1117 uinfo = node_to_item(node, struct audio_usecase, list);
1118 if (uinfo->type != PCM_CAPTURE) {
1119 out_device = uinfo->stream.out->devices;
1120 break;
1121 }
1122 }
1123 }
1124 platform_set_echo_reference(adev, true, out_device);
1125 in->ec_opened = true;
1126 }
1127 }
1128 } else if (usecase->type == TRANSCODE_LOOPBACK_TX) {
1129 snd_device = usecase->in_snd_device;
1130 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001132 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001133
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001134#ifdef DS1_DOLBY_DAP_ENABLED
1135 audio_extn_dolby_set_dmid(adev);
1136 audio_extn_dolby_set_endpoint(adev);
1137#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001138 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001139 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301140 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001141 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001142 if (audio_extn_is_maxx_audio_enabled())
1143 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301144 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301145 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1146 out = usecase->stream.out;
1147 if (out && out->compr)
1148 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1149 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301150
1151 if (usecase->type == PCM_CAPTURE) {
1152 in = usecase->stream.in;
1153 if (in && is_loopback_input_device(in->device)) {
1154 ALOGD("%s: set custom mtmx params v1", __func__);
1155 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1156 }
1157 } else {
1158 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1159 }
Manish Dewangan58229382017-02-02 15:48:41 +05301160
Andy Hung756ecc12018-10-19 17:47:12 -07001161 // we shouldn't truncate mixer_path
1162 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1163 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1164 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001165 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001166 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301167 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1168 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1169 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1170 if (parms) {
1171 audio_extn_fm_set_parameters(adev, parms);
1172 str_parms_destroy(parms);
1173 }
1174 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175 ALOGV("%s: exit", __func__);
1176 return 0;
1177}
1178
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001179int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001180 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001181{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001182 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001183 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301184 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001185
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301186 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001187 return -EINVAL;
1188
1189 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301190 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001191 snd_device = usecase->in_snd_device;
1192 else
1193 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001194 // we shouldn't truncate mixer_path
1195 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1196 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1197 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001198 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001199 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001200 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001201 if (usecase->type == PCM_CAPTURE) {
1202 struct stream_in *in = usecase->stream.in;
1203 if (in && in->ec_opened) {
1204 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
1205 in->ec_opened = false;
1206 }
1207 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001208 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301209 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301210
1211 if (usecase->type == PCM_CAPTURE) {
1212 in = usecase->stream.in;
1213 if (in && is_loopback_input_device(in->device)) {
1214 ALOGD("%s: reset custom mtmx params v1", __func__);
1215 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1216 }
1217 } else {
1218 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1219 }
1220
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001221 if ((usecase->type == PCM_PLAYBACK) &&
1222 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301223 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 ALOGV("%s: exit", __func__);
1226 return 0;
1227}
1228
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001229int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001230 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301232 int i, num_devices = 0;
1233 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001234 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1235
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001236 if (snd_device < SND_DEVICE_MIN ||
1237 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001238 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001239 return -EINVAL;
1240 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001241
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001242 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001243 ALOGE("%s: Invalid sound device returned", __func__);
1244 return -EINVAL;
1245 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001246
1247 adev->snd_dev_ref_cnt[snd_device]++;
1248
1249 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1250 (platform_split_snd_device(adev->platform,
1251 snd_device,
1252 &num_devices,
1253 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001254 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001255 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001256 return 0;
1257 }
1258
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001259 if (audio_extn_spkr_prot_is_enabled())
1260 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001261
Aalique Grahame22e49102018-12-18 14:23:57 -08001262 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1263
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001264 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1265 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001266 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1267 goto err;
1268 }
1269 audio_extn_dev_arbi_acquire(snd_device);
1270 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001271 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001272 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001273 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001274 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001275 } else if (platform_split_snd_device(adev->platform,
1276 snd_device,
1277 &num_devices,
1278 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301279 for (i = 0; i < num_devices; i++) {
1280 enable_snd_device(adev, new_snd_devices[i]);
1281 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001282 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001283 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001284 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301285
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301286
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001287 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1288 (audio_extn_a2dp_start_playback() < 0)) {
1289 ALOGE(" fail to configure A2dp Source control path ");
1290 goto err;
1291 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001292
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001293 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1294 (audio_extn_a2dp_start_capture() < 0)) {
1295 ALOGE(" fail to configure A2dp Sink control path ");
1296 goto err;
1297 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301298
Zhou Song12c29502019-03-16 10:37:18 +08001299 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1300 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1301 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1302 (audio_extn_sco_start_configuration() < 0)) {
1303 ALOGE(" fail to configure sco control path ");
1304 goto err;
1305 }
1306
Zhou Song4721e282019-08-26 14:16:12 +08001307 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001308 /* due to the possibility of calibration overwrite between listen
1309 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001310 audio_extn_sound_trigger_update_device_status(snd_device,
1311 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301312 audio_extn_listen_update_device_status(snd_device,
1313 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001314 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001315 audio_extn_sound_trigger_update_device_status(snd_device,
1316 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301317 audio_extn_listen_update_device_status(snd_device,
1318 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001319 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001320 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001321 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001322 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301323
1324 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1325 !adev->native_playback_enabled &&
1326 audio_is_true_native_stream_active(adev)) {
1327 ALOGD("%s: %d: napb: enabling native mode in hardware",
1328 __func__, __LINE__);
1329 audio_route_apply_and_update_path(adev->audio_route,
1330 "true-native-mode");
1331 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301332 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301333 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1334 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001335 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001336 ALOGD("%s: init ec ref loopback", __func__);
1337 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1338 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001339 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001341err:
1342 adev->snd_dev_ref_cnt[snd_device]--;
1343 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344}
1345
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001346int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001347 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301349 int i, num_devices = 0;
1350 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001351 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1352
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001353 if (snd_device < SND_DEVICE_MIN ||
1354 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001355 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001356 return -EINVAL;
1357 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001358
1359 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1360 ALOGE("%s: Invalid sound device returned", __func__);
1361 return -EINVAL;
1362 }
1363
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001364 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1365 ALOGE("%s: device ref cnt is already 0", __func__);
1366 return -EINVAL;
1367 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001368
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001369 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001370
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001371
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001372 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001373 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301374
Aalique Grahame22e49102018-12-18 14:23:57 -08001375 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1376
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001377 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1378 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001379 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001380
1381 // when speaker device is disabled, reset swap.
1382 // will be renabled on usecase start
1383 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001384 } else if (platform_split_snd_device(adev->platform,
1385 snd_device,
1386 &num_devices,
1387 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301388 for (i = 0; i < num_devices; i++) {
1389 disable_snd_device(adev, new_snd_devices[i]);
1390 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001391 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001392 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001393 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001394 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001395
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001396 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301397 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001398 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001399 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001400 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001401 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301402 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001403 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301404 adev->native_playback_enabled) {
1405 ALOGD("%s: %d: napb: disabling native mode in hardware",
1406 __func__, __LINE__);
1407 audio_route_reset_and_update_path(adev->audio_route,
1408 "true-native-mode");
1409 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001410 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301411 adev->asrc_mode_enabled) {
1412 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301413 disable_asrc_mode(adev);
1414 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001415 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301416 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001417 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001418 ALOGD("%s: deinit ec ref loopback", __func__);
1419 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1420 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001421
1422 audio_extn_utils_release_snd_device(snd_device);
1423 } else {
1424 if (platform_split_snd_device(adev->platform,
1425 snd_device,
1426 &num_devices,
1427 new_snd_devices) == 0) {
1428 for (i = 0; i < num_devices; i++) {
1429 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1430 }
1431 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001432 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434 return 0;
1435}
1436
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001437/*
1438 legend:
1439 uc - existing usecase
1440 new_uc - new usecase
1441 d1, d11, d2 - SND_DEVICE enums
1442 a1, a2 - corresponding ANDROID device enums
1443 B1, B2 - backend strings
1444
1445case 1
1446 uc->dev d1 (a1) B1
1447 new_uc->dev d1 (a1), d2 (a2) B1, B2
1448
1449 resolution: disable and enable uc->dev on d1
1450
1451case 2
1452 uc->dev d1 (a1) B1
1453 new_uc->dev d11 (a1) B1
1454
1455 resolution: need to switch uc since d1 and d11 are related
1456 (e.g. speaker and voice-speaker)
1457 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1458
1459case 3
1460 uc->dev d1 (a1) B1
1461 new_uc->dev d2 (a2) B2
1462
1463 resolution: no need to switch uc
1464
1465case 4
1466 uc->dev d1 (a1) B1
1467 new_uc->dev d2 (a2) B1
1468
1469 resolution: disable enable uc-dev on d2 since backends match
1470 we cannot enable two streams on two different devices if they
1471 share the same backend. e.g. if offload is on speaker device using
1472 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1473 using the same backend, offload must also be switched to voice-handset.
1474
1475case 5
1476 uc->dev d1 (a1) B1
1477 new_uc->dev d1 (a1), d2 (a2) B1
1478
1479 resolution: disable enable uc-dev on d2 since backends match
1480 we cannot enable two streams on two different devices if they
1481 share the same backend.
1482
1483case 6
1484 uc->dev d1 (a1) B1
1485 new_uc->dev d2 (a1) B2
1486
1487 resolution: no need to switch
1488
1489case 7
1490 uc->dev d1 (a1), d2 (a2) B1, B2
1491 new_uc->dev d1 (a1) B1
1492
1493 resolution: no need to switch
1494
Zhou Song4ba65882018-07-09 14:48:07 +08001495case 8
1496 uc->dev d1 (a1) B1
1497 new_uc->dev d11 (a1), d2 (a2) B1, B2
1498 resolution: compared to case 1, for this case, d1 and d11 are related
1499 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001500*/
1501static snd_device_t derive_playback_snd_device(void * platform,
1502 struct audio_usecase *uc,
1503 struct audio_usecase *new_uc,
1504 snd_device_t new_snd_device)
1505{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301506 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001507
1508 snd_device_t d1 = uc->out_snd_device;
1509 snd_device_t d2 = new_snd_device;
1510
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301511 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301512 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301513 a1 = uc->stream.inout->out_config.devices;
1514 a2 = new_uc->stream.inout->out_config.devices;
1515 break;
1516 default :
1517 a1 = uc->stream.out->devices;
1518 a2 = new_uc->stream.out->devices;
1519 break;
1520 }
1521
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001522 // Treat as a special case when a1 and a2 are not disjoint
1523 if ((a1 != a2) && (a1 & a2)) {
1524 snd_device_t d3[2];
1525 int num_devices = 0;
1526 int ret = platform_split_snd_device(platform,
1527 popcount(a1) > 1 ? d1 : d2,
1528 &num_devices,
1529 d3);
1530 if (ret < 0) {
1531 if (ret != -ENOSYS) {
1532 ALOGW("%s failed to split snd_device %d",
1533 __func__,
1534 popcount(a1) > 1 ? d1 : d2);
1535 }
1536 goto end;
1537 }
1538
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001539 if (platform_check_backends_match(d3[0], d3[1])) {
1540 return d2; // case 5
1541 } else {
Samyak Jaind826b502019-07-17 16:16:42 +05301542 if (popcount(a1) > 1)
1543 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001544 // check if d1 is related to any of d3's
1545 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001546 return d1; // case 1
1547 else
1548 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001549 }
1550 } else {
1551 if (platform_check_backends_match(d1, d2)) {
1552 return d2; // case 2, 4
1553 } else {
1554 return d1; // case 6, 3
1555 }
1556 }
1557
1558end:
1559 return d2; // return whatever was calculated before.
1560}
1561
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001562static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301563 struct audio_usecase *uc_info,
1564 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001565{
1566 struct listnode *node;
1567 struct audio_usecase *usecase;
1568 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301569 snd_device_t uc_derive_snd_device;
1570 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001571 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1572 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001573 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301574 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001575 /*
1576 * This function is to make sure that all the usecases that are active on
1577 * the hardware codec backend are always routed to any one device that is
1578 * handled by the hardware codec.
1579 * For example, if low-latency and deep-buffer usecases are currently active
1580 * on speaker and out_set_parameters(headset) is received on low-latency
1581 * output, then we have to make sure deep-buffer is also switched to headset,
1582 * because of the limitation that both the devices cannot be enabled
1583 * at the same time as they share the same backend.
1584 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001585 /*
1586 * This call is to check if we need to force routing for a particular stream
1587 * If there is a backend configuration change for the device when a
1588 * new stream starts, then ADM needs to be closed and re-opened with the new
1589 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001590 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001591 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001592 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1593 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301594 /* For a2dp device reconfigure all active sessions
1595 * with new AFE encoder format based on a2dp state
1596 */
1597 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1598 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1599 audio_extn_a2dp_is_force_device_switch()) {
1600 force_routing = true;
1601 force_restart_session = true;
1602 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301603 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001606 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001607 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001608 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1609 switch_device[i] = false;
1610
1611 list_for_each(node, &adev->usecase_list) {
1612 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001613
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301614 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1615 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301616 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301617 platform_get_snd_device_name(usecase->out_snd_device),
1618 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301619 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1620 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301621 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1622 usecase, uc_info, snd_device);
1623 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1624 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1625 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1626 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001627 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301628 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1629 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1630 ((force_restart_session) ||
1631 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301632 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1633 __func__, use_case_table[usecase->id],
1634 platform_get_snd_device_name(usecase->out_snd_device));
1635 disable_audio_route(adev, usecase);
1636 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301637 /* Enable existing usecase on derived playback device */
1638 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301639 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301640 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001641 }
1642 }
1643
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301644 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1645 num_uc_to_switch);
1646
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001647 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001648 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001649
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301650 /* Make sure the previous devices to be disabled first and then enable the
1651 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 list_for_each(node, &adev->usecase_list) {
1653 usecase = node_to_item(node, struct audio_usecase, list);
1654 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001655 /* Check if output sound device to be switched can be split and if any
1656 of the split devices match with derived sound device */
1657 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1658 &num_devices, split_snd_devices) == 0) {
1659 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1660 for (i = 0; i < num_devices; i++) {
1661 /* Disable devices that do not match with derived sound device */
1662 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1663 disable_snd_device(adev, split_snd_devices[i]);
1664 }
1665 } else {
1666 disable_snd_device(adev, usecase->out_snd_device);
1667 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001668 }
1669 }
1670
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001671 list_for_each(node, &adev->usecase_list) {
1672 usecase = node_to_item(node, struct audio_usecase, list);
1673 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001674 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1675 &num_devices, split_snd_devices) == 0) {
1676 /* Enable derived sound device only if it does not match with
1677 one of the split sound devices. This is because the matching
1678 sound device was not disabled */
1679 bool should_enable = true;
1680 for (i = 0; i < num_devices; i++) {
1681 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1682 should_enable = false;
1683 break;
1684 }
1685 }
1686 if (should_enable)
1687 enable_snd_device(adev, derive_snd_device[usecase->id]);
1688 } else {
1689 enable_snd_device(adev, derive_snd_device[usecase->id]);
1690 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001691 }
1692 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001693
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001694 /* Re-route all the usecases on the shared backend other than the
1695 specified usecase to new snd devices */
1696 list_for_each(node, &adev->usecase_list) {
1697 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301698 /* Update the out_snd_device only before enabling the audio route */
1699 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301700 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301701 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301702 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301703 use_case_table[usecase->id],
1704 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001705 /* Update voc calibration before enabling VoIP route */
1706 if (usecase->type == VOIP_CALL)
1707 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001708 usecase->out_snd_device,
1709 platform_get_input_snd_device(
1710 adev->platform, NULL,
1711 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301712 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301713 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001714 out_set_voip_volume(&usecase->stream.out->stream,
1715 usecase->stream.out->volume_l,
1716 usecase->stream.out->volume_r);
1717 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301718 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001719 }
1720 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001721 }
1722}
1723
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301724static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001725 struct audio_usecase *uc_info,
1726 snd_device_t snd_device)
1727{
1728 struct listnode *node;
1729 struct audio_usecase *usecase;
1730 bool switch_device[AUDIO_USECASE_MAX];
1731 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301732 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001733 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001734
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301735 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1736 snd_device);
1737 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301738
1739 /*
1740 * Make sure out devices is checked against out codec backend device and
1741 * also in devices against in codec backend. Checking out device against in
1742 * codec backend or vice versa causes issues.
1743 */
1744 if (uc_info->type == PCM_CAPTURE)
1745 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001746 /*
1747 * This function is to make sure that all the active capture usecases
1748 * are always routed to the same input sound device.
1749 * For example, if audio-record and voice-call usecases are currently
1750 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1751 * is received for voice call then we have to make sure that audio-record
1752 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1753 * because of the limitation that two devices cannot be enabled
1754 * at the same time if they share the same backend.
1755 */
1756 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1757 switch_device[i] = false;
1758
1759 list_for_each(node, &adev->usecase_list) {
1760 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301761 /*
1762 * TODO: Enhance below condition to handle BT sco/USB multi recording
1763 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001764 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001765 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301766 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301767 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301768 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301769 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001770 ((uc_info->type == VOICE_CALL &&
1771 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1772 platform_check_backends_match(snd_device,\
1773 usecase->in_snd_device)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001774 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001775 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1776 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001777 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001778 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001779 switch_device[usecase->id] = true;
1780 num_uc_to_switch++;
1781 }
1782 }
1783
1784 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001785 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001786
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301787 /* Make sure the previous devices to be disabled first and then enable the
1788 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001789 list_for_each(node, &adev->usecase_list) {
1790 usecase = node_to_item(node, struct audio_usecase, list);
1791 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001792 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001793 }
1794 }
1795
1796 list_for_each(node, &adev->usecase_list) {
1797 usecase = node_to_item(node, struct audio_usecase, list);
1798 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001799 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001800 }
1801 }
1802
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001803 /* Re-route all the usecases on the shared backend other than the
1804 specified usecase to new snd devices */
1805 list_for_each(node, &adev->usecase_list) {
1806 usecase = node_to_item(node, struct audio_usecase, list);
1807 /* Update the in_snd_device only before enabling the audio route */
1808 if (switch_device[usecase->id] ) {
1809 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001810 if (usecase->type != VOICE_CALL) {
1811 /* Update voc calibration before enabling VoIP route */
1812 if (usecase->type == VOIP_CALL)
1813 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001814 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001815 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301816 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001817 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001818 }
1819 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001820 }
1821}
1822
Mingming Yin3a941d42016-02-17 18:08:05 -08001823static void reset_hdmi_sink_caps(struct stream_out *out) {
1824 int i = 0;
1825
1826 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1827 out->supported_channel_masks[i] = 0;
1828 }
1829 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1830 out->supported_formats[i] = 0;
1831 }
1832 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1833 out->supported_sample_rates[i] = 0;
1834 }
1835}
1836
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001838static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839{
Mingming Yin3a941d42016-02-17 18:08:05 -08001840 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001841 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842
Mingming Yin3a941d42016-02-17 18:08:05 -08001843 reset_hdmi_sink_caps(out);
1844
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001845 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001846 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001847 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001848 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001849 }
1850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001853 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001854 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001855 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1856 case 6:
1857 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1858 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1859 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1860 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1861 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1862 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 break;
1864 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001865 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001866 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 break;
1868 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001869
1870 // check channel format caps
1871 i = 0;
1872 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1873 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1874 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1875 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1876 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1877 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1878 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1879 }
1880
Ben Romberger1aaaf862017-04-06 17:49:46 -07001881 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1882 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1883 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1884 }
1885
Mingming Yin3a941d42016-02-17 18:08:05 -08001886 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1887 ALOGV(":%s HDMI supports DTS format", __func__);
1888 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1889 }
1890
1891 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1892 ALOGV(":%s HDMI supports DTS HD format", __func__);
1893 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1894 }
1895
Naresh Tanniru928f0862017-04-07 16:44:23 -07001896 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1897 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1898 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1899 }
1900
Mingming Yin3a941d42016-02-17 18:08:05 -08001901
1902 // check sample rate caps
1903 i = 0;
1904 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1905 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1906 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1907 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1908 }
1909 }
1910
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001911 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912}
1913
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001914static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1915 uint32_t *supported_sample_rates __unused,
1916 uint32_t max_rates __unused)
1917{
1918 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1919 supported_sample_rates,
1920 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301921 ssize_t i = 0;
1922
1923 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001924 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1925 supported_sample_rates[i]);
1926 }
1927 return count;
1928}
1929
1930static inline int read_usb_sup_channel_masks(bool is_playback,
1931 audio_channel_mask_t *supported_channel_masks,
1932 uint32_t max_masks)
1933{
1934 int channels = audio_extn_usb_get_max_channels(is_playback);
1935 int channel_count;
1936 uint32_t num_masks = 0;
1937 if (channels > MAX_HIFI_CHANNEL_COUNT)
1938 channels = MAX_HIFI_CHANNEL_COUNT;
1939
1940 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001941 // start from 2 channels as framework currently doesn't support mono.
1942 if (channels >= FCC_2) {
1943 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1944 }
1945 for (channel_count = FCC_2;
1946 channel_count <= channels && num_masks < max_masks;
1947 ++channel_count) {
1948 supported_channel_masks[num_masks++] =
1949 audio_channel_mask_for_index_assignment_from_count(channel_count);
1950 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001951 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001952 // For capture we report all supported channel masks from 1 channel up.
1953 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001954 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1955 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001956 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1957 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1958 if (channel_count <= FCC_2) {
1959 mask = audio_channel_in_mask_from_count(channel_count);
1960 supported_channel_masks[num_masks++] = mask;
1961 }
1962 const audio_channel_mask_t index_mask =
1963 audio_channel_mask_for_index_assignment_from_count(channel_count);
1964 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1965 supported_channel_masks[num_masks++] = index_mask;
1966 }
1967 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001968 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301969
vincenttewf51c94e2019-05-07 10:28:53 +08001970 for (size_t i = 0; i < num_masks; ++i) {
1971 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1972 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301973 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001974 return num_masks;
1975}
1976
1977static inline int read_usb_sup_formats(bool is_playback __unused,
1978 audio_format_t *supported_formats,
1979 uint32_t max_formats __unused)
1980{
1981 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1982 switch (bitwidth) {
1983 case 24:
1984 // XXX : usb.c returns 24 for s24 and s24_le?
1985 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1986 break;
1987 case 32:
1988 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1989 break;
1990 case 16:
1991 default :
1992 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1993 break;
1994 }
1995 ALOGV("%s: %s supported format %d", __func__,
1996 is_playback ? "P" : "C", bitwidth);
1997 return 1;
1998}
1999
2000static inline int read_usb_sup_params_and_compare(bool is_playback,
2001 audio_format_t *format,
2002 audio_format_t *supported_formats,
2003 uint32_t max_formats,
2004 audio_channel_mask_t *mask,
2005 audio_channel_mask_t *supported_channel_masks,
2006 uint32_t max_masks,
2007 uint32_t *rate,
2008 uint32_t *supported_sample_rates,
2009 uint32_t max_rates) {
2010 int ret = 0;
2011 int num_formats;
2012 int num_masks;
2013 int num_rates;
2014 int i;
2015
2016 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2017 max_formats);
2018 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2019 max_masks);
2020
2021 num_rates = read_usb_sup_sample_rates(is_playback,
2022 supported_sample_rates, max_rates);
2023
2024#define LUT(table, len, what, dflt) \
2025 for (i=0; i<len && (table[i] != what); i++); \
2026 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2027
2028 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2029 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2030 LUT(supported_sample_rates, num_rates, *rate, 0);
2031
2032#undef LUT
2033 return ret < 0 ? -EINVAL : 0; // HACK TBD
2034}
2035
Alexy Josephb1379942016-01-29 15:49:38 -08002036audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002037 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002038{
2039 struct audio_usecase *usecase;
2040 struct listnode *node;
2041
2042 list_for_each(node, &adev->usecase_list) {
2043 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002044 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002045 ALOGV("%s: usecase id %d", __func__, usecase->id);
2046 return usecase->id;
2047 }
2048 }
2049 return USECASE_INVALID;
2050}
2051
Alexy Josephb1379942016-01-29 15:49:38 -08002052struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002053 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002054{
2055 struct audio_usecase *usecase;
2056 struct listnode *node;
2057
2058 list_for_each(node, &adev->usecase_list) {
2059 usecase = node_to_item(node, struct audio_usecase, list);
2060 if (usecase->id == uc_id)
2061 return usecase;
2062 }
2063 return NULL;
2064}
2065
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302066/*
2067 * is a true native playback active
2068 */
2069bool audio_is_true_native_stream_active(struct audio_device *adev)
2070{
2071 bool active = false;
2072 int i = 0;
2073 struct listnode *node;
2074
2075 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2076 ALOGV("%s:napb: not in true mode or non hdphones device",
2077 __func__);
2078 active = false;
2079 goto exit;
2080 }
2081
2082 list_for_each(node, &adev->usecase_list) {
2083 struct audio_usecase *uc;
2084 uc = node_to_item(node, struct audio_usecase, list);
2085 struct stream_out *curr_out =
2086 (struct stream_out*) uc->stream.out;
2087
2088 if (curr_out && PCM_PLAYBACK == uc->type) {
2089 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2090 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2091 uc->id, curr_out->sample_rate,
2092 curr_out->bit_width,
2093 platform_get_snd_device_name(uc->out_snd_device));
2094
2095 if (is_offload_usecase(uc->id) &&
2096 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2097 active = true;
2098 ALOGD("%s:napb:native stream detected", __func__);
2099 }
2100 }
2101 }
2102exit:
2103 return active;
2104}
2105
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002106uint32_t adev_get_dsp_bit_width_enforce_mode()
2107{
2108 if (adev == NULL) {
2109 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2110 return 0;
2111 }
2112 return adev->dsp_bit_width_enforce_mode;
2113}
2114
2115static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2116{
2117 char value[PROPERTY_VALUE_MAX];
2118 int trial;
2119 uint32_t dsp_bit_width_enforce_mode = 0;
2120
2121 if (!mixer) {
2122 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2123 __func__);
2124 return 0;
2125 }
2126
2127 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2128 value, NULL) > 0) {
2129 trial = atoi(value);
2130 switch (trial) {
2131 case 16:
2132 dsp_bit_width_enforce_mode = 16;
2133 break;
2134 case 24:
2135 dsp_bit_width_enforce_mode = 24;
2136 break;
2137 case 32:
2138 dsp_bit_width_enforce_mode = 32;
2139 break;
2140 default:
2141 dsp_bit_width_enforce_mode = 0;
2142 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2143 break;
2144 }
2145 }
2146
2147 return dsp_bit_width_enforce_mode;
2148}
2149
2150static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2151 uint32_t enforce_mode,
2152 bool enable)
2153{
2154 struct mixer_ctl *ctl = NULL;
2155 const char *mixer_ctl_name = "ASM Bit Width";
2156 uint32_t asm_bit_width_mode = 0;
2157
2158 if (enforce_mode == 0) {
2159 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2160 return;
2161 }
2162
2163 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2164 if (!ctl) {
2165 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2166 __func__, mixer_ctl_name);
2167 return;
2168 }
2169
2170 if (enable)
2171 asm_bit_width_mode = enforce_mode;
2172 else
2173 asm_bit_width_mode = 0;
2174
2175 ALOGV("%s DSP bit width feature status is %d width=%d",
2176 __func__, enable, asm_bit_width_mode);
2177 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2178 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2179 asm_bit_width_mode);
2180
2181 return;
2182}
2183
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302184/*
2185 * if native DSD playback active
2186 */
2187bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2188{
2189 bool active = false;
2190 struct listnode *node = NULL;
2191 struct audio_usecase *uc = NULL;
2192 struct stream_out *curr_out = NULL;
2193
2194 list_for_each(node, &adev->usecase_list) {
2195 uc = node_to_item(node, struct audio_usecase, list);
2196 curr_out = (struct stream_out*) uc->stream.out;
2197
2198 if (curr_out && PCM_PLAYBACK == uc->type &&
2199 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2200 active = true;
2201 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302202 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302203 }
2204 }
2205 return active;
2206}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302207
2208static bool force_device_switch(struct audio_usecase *usecase)
2209{
2210 bool ret = false;
2211 bool is_it_true_mode = false;
2212
Zhou Song30f2c3e2018-02-08 14:02:15 +08002213 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302214 usecase->type == TRANSCODE_LOOPBACK_RX ||
2215 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002216 return false;
2217 }
2218
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002219 if(usecase->stream.out == NULL) {
2220 ALOGE("%s: stream.out is NULL", __func__);
2221 return false;
2222 }
2223
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302224 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002225 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2226 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2227 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302228 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2229 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2230 (!is_it_true_mode && adev->native_playback_enabled)){
2231 ret = true;
2232 ALOGD("napb: time to toggle native mode");
2233 }
2234 }
2235
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302236 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302237 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2238 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002239 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302240 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302241 ALOGD("Force a2dp device switch to update new encoder config");
2242 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002243 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302244
Florian Pfister1a84f312018-07-19 14:38:18 +02002245 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302246 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2247 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002248 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302249 return ret;
2250}
2251
Aalique Grahame22e49102018-12-18 14:23:57 -08002252static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2253{
2254 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2255}
2256
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302257bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2258{
2259 bool ret=false;
2260 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2261 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2262 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2263 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2264 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2265 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2266 ret = true;
2267
2268 return ret;
2269}
2270
2271bool is_a2dp_device(snd_device_t out_snd_device)
2272{
2273 bool ret=false;
2274 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2275 ret = true;
2276
2277 return ret;
2278}
2279
2280bool is_bt_soc_on(struct audio_device *adev)
2281{
2282 struct mixer_ctl *ctl;
2283 char *mixer_ctl_name = "BT SOC status";
2284 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2285 bool bt_soc_status = true;
2286 if (!ctl) {
2287 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2288 __func__, mixer_ctl_name);
2289 /*This is to ensure we dont break targets which dont have the kernel change*/
2290 return true;
2291 }
2292 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2293 ALOGD("BT SOC status: %d",bt_soc_status);
2294 return bt_soc_status;
2295}
2296
Zhou Song4721e282019-08-26 14:16:12 +08002297static int configure_btsco_sample_rate(snd_device_t snd_device)
2298{
2299 struct mixer_ctl *ctl = NULL;
2300 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2301 char *rate_str = NULL;
2302 bool is_rx_dev = true;
2303
2304 if (is_btsco_device(snd_device, snd_device)) {
2305 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2306 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2307 if (!ctl_sr_tx || !ctl_sr_rx) {
2308 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2309 if (!ctl_sr)
2310 return -ENOSYS;
2311 }
2312
2313 switch (snd_device) {
2314 case SND_DEVICE_OUT_BT_SCO:
2315 rate_str = "KHZ_8";
2316 break;
2317 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2318 case SND_DEVICE_IN_BT_SCO_MIC:
2319 rate_str = "KHZ_8";
2320 is_rx_dev = false;
2321 break;
2322 case SND_DEVICE_OUT_BT_SCO_WB:
2323 rate_str = "KHZ_16";
2324 break;
2325 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2326 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2327 rate_str = "KHZ_16";
2328 is_rx_dev = false;
2329 break;
2330 default:
2331 return 0;
2332 }
2333
2334 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2335 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2336 return -ENOSYS;
2337 }
2338 return 0;
2339}
2340
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302341int out_standby_l(struct audio_stream *stream);
2342
Eric Laurent637e2d42018-11-15 12:24:31 -08002343struct stream_in *adev_get_active_input(const struct audio_device *adev)
2344{
2345 struct listnode *node;
2346 struct stream_in *last_active_in = NULL;
2347
2348 /* Get last added active input.
2349 * TODO: We may use a priority mechanism to pick highest priority active source */
2350 list_for_each(node, &adev->usecase_list)
2351 {
2352 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2353 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2354 last_active_in = usecase->stream.in;
2355 }
2356
2357 return last_active_in;
2358}
2359
2360struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2361{
2362 struct listnode *node;
2363
2364 /* First check active inputs with voice communication source and then
2365 * any input if audio mode is in communication */
2366 list_for_each(node, &adev->usecase_list)
2367 {
2368 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2369 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2370 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2371 return usecase->stream.in;
2372 }
2373 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2374 return adev_get_active_input(adev);
2375
2376 return NULL;
2377}
2378
Carter Hsu2e429db2019-05-14 18:50:52 +08002379/*
2380 * Aligned with policy.h
2381 */
2382static inline int source_priority(int inputSource)
2383{
2384 switch (inputSource) {
2385 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2386 return 9;
2387 case AUDIO_SOURCE_CAMCORDER:
2388 return 8;
2389 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2390 return 7;
2391 case AUDIO_SOURCE_UNPROCESSED:
2392 return 6;
2393 case AUDIO_SOURCE_MIC:
2394 return 5;
2395 case AUDIO_SOURCE_ECHO_REFERENCE:
2396 return 4;
2397 case AUDIO_SOURCE_FM_TUNER:
2398 return 3;
2399 case AUDIO_SOURCE_VOICE_RECOGNITION:
2400 return 2;
2401 case AUDIO_SOURCE_HOTWORD:
2402 return 1;
2403 default:
2404 break;
2405 }
2406 return 0;
2407}
2408
2409static struct stream_in *get_priority_input(struct audio_device *adev)
2410{
2411 struct listnode *node;
2412 struct audio_usecase *usecase;
2413 int last_priority = 0, priority;
2414 struct stream_in *priority_in = NULL;
2415 struct stream_in *in;
2416
2417 list_for_each(node, &adev->usecase_list) {
2418 usecase = node_to_item(node, struct audio_usecase, list);
2419 if (usecase->type == PCM_CAPTURE) {
2420 in = usecase->stream.in;
2421 if (!in)
2422 continue;
2423 priority = source_priority(in->source);
2424
2425 if (priority > last_priority) {
2426 last_priority = priority;
2427 priority_in = in;
2428 }
2429 }
2430 }
2431 return priority_in;
2432}
2433
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002434int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002436 snd_device_t out_snd_device = SND_DEVICE_NONE;
2437 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002438 struct audio_usecase *usecase = NULL;
2439 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002440 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002441 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302442 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002443 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002444 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302446 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2447
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002448 usecase = get_usecase_from_list(adev, uc_id);
2449 if (usecase == NULL) {
2450 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2451 return -EINVAL;
2452 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002454 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002455 (usecase->type == VOIP_CALL) ||
2456 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302457 if(usecase->stream.out == NULL) {
2458 ALOGE("%s: stream.out is NULL", __func__);
2459 return -EINVAL;
2460 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002461 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002462 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002463 in_snd_device = platform_get_input_snd_device(adev->platform,
2464 NULL,
2465 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002466 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302467 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302468 if (usecase->stream.inout == NULL) {
2469 ALOGE("%s: stream.inout is NULL", __func__);
2470 return -EINVAL;
2471 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302472 stream_out.devices = usecase->stream.inout->out_config.devices;
2473 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2474 stream_out.format = usecase->stream.inout->out_config.format;
2475 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2476 out_snd_device = platform_get_output_snd_device(adev->platform,
2477 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302478 usecase->devices = out_snd_device;
2479 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2480 if (usecase->stream.inout == NULL) {
2481 ALOGE("%s: stream.inout is NULL", __func__);
2482 return -EINVAL;
2483 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002484 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302485 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002486 } else {
2487 /*
2488 * If the voice call is active, use the sound devices of voice call usecase
2489 * so that it would not result any device switch. All the usecases will
2490 * be switched to new device when select_devices() is called for voice call
2491 * usecase. This is to avoid switching devices for voice call when
2492 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002493 * choose voice call device only if the use case device is
2494 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002495 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002496 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002497 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002498 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002499 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2500 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302501 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2502 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002503 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2504 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002505 in_snd_device = vc_usecase->in_snd_device;
2506 out_snd_device = vc_usecase->out_snd_device;
2507 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002508 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002509 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002510 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002511 if ((voip_usecase != NULL) &&
2512 (usecase->type == PCM_PLAYBACK) &&
2513 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002514 out_snd_device_backend_match = platform_check_backends_match(
2515 voip_usecase->out_snd_device,
2516 platform_get_output_snd_device(
2517 adev->platform,
2518 usecase->stream.out));
2519 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002520 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002521 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2522 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002523 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002524 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002525 in_snd_device = voip_usecase->in_snd_device;
2526 out_snd_device = voip_usecase->out_snd_device;
2527 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002528 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002529 hfp_ucid = audio_extn_hfp_get_usecase();
2530 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002531 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002532 in_snd_device = hfp_usecase->in_snd_device;
2533 out_snd_device = hfp_usecase->out_snd_device;
2534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002535 }
2536 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302537 if (usecase->stream.out == NULL) {
2538 ALOGE("%s: stream.out is NULL", __func__);
2539 return -EINVAL;
2540 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002541 usecase->devices = usecase->stream.out->devices;
2542 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002543 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002544 struct stream_out *voip_out = adev->primary_output;
2545 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002546 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002547 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002548 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002549
Eric Laurent637e2d42018-11-15 12:24:31 -08002550 if (voip_usecase)
2551 voip_out = voip_usecase->stream.out;
2552
2553 if (usecase->stream.out == voip_out && voip_in != NULL)
2554 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002555 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002556 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302557 if (usecase->stream.in == NULL) {
2558 ALOGE("%s: stream.in is NULL", __func__);
2559 return -EINVAL;
2560 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002561 usecase->devices = usecase->stream.in->device;
2562 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002563 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002564 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002565 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002566 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002567
2568 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002569 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2570 USECASE_AUDIO_PLAYBACK_VOIP);
2571
Carter Hsu2e429db2019-05-14 18:50:52 +08002572 usecase->stream.in->enable_ec_port = false;
2573
Eric Laurent637e2d42018-11-15 12:24:31 -08002574 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2575 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2576 } else if (voip_usecase) {
2577 out_device = voip_usecase->stream.out->devices;
2578 } else if (adev->primary_output &&
2579 !adev->primary_output->standby) {
2580 out_device = adev->primary_output->devices;
2581 } else {
2582 /* forcing speaker o/p device to get matching i/p pair
2583 in case o/p is not routed from same primary HAL */
2584 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2585 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002586 priority_in = voip_in;
2587 } else {
2588 /* get the input with the highest priority source*/
2589 priority_in = get_priority_input(adev);
2590
2591 if (!priority_in)
2592 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002593 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002594
Eric Laurent637e2d42018-11-15 12:24:31 -08002595 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002596 priority_in,
Eric Laurent637e2d42018-11-15 12:24:31 -08002597 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002598 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002599 }
2600 }
2601
2602 if (out_snd_device == usecase->out_snd_device &&
2603 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302604
2605 if (!force_device_switch(usecase))
2606 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 }
2608
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302609 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002610 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302611 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2612 return 0;
2613 }
2614
Aalique Grahame22e49102018-12-18 14:23:57 -08002615 if (out_snd_device != SND_DEVICE_NONE &&
2616 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2617 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2618 __func__,
2619 use_case_table[uc_id],
2620 adev->last_logged_snd_device[uc_id][0],
2621 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2622 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2623 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2624 -1,
2625 out_snd_device,
2626 platform_get_snd_device_name(out_snd_device),
2627 platform_get_snd_device_acdb_id(out_snd_device));
2628 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2629 }
2630 if (in_snd_device != SND_DEVICE_NONE &&
2631 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2632 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2633 __func__,
2634 use_case_table[uc_id],
2635 adev->last_logged_snd_device[uc_id][1],
2636 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2637 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2638 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2639 -1,
2640 in_snd_device,
2641 platform_get_snd_device_name(in_snd_device),
2642 platform_get_snd_device_acdb_id(in_snd_device));
2643 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2644 }
2645
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 /*
2648 * Limitation: While in call, to do a device switch we need to disable
2649 * and enable both RX and TX devices though one of them is same as current
2650 * device.
2651 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002652 if ((usecase->type == VOICE_CALL) &&
2653 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2654 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002655 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002656 }
2657
2658 if (((usecase->type == VOICE_CALL) ||
2659 (usecase->type == VOIP_CALL)) &&
2660 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2661 /* Disable sidetone only if voice/voip call already exists */
2662 if (voice_is_call_state_active(adev) ||
2663 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002664 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002665
2666 /* Disable aanc only if voice call exists */
2667 if (voice_is_call_state_active(adev))
2668 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002669 }
2670
Aalique Grahame22e49102018-12-18 14:23:57 -08002671 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2672 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002673 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302674 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002675 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2676 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2677 else
2678 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302679 }
2680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002681 /* Disable current sound devices */
2682 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002683 disable_audio_route(adev, usecase);
2684 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 }
2686
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002687 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002688 disable_audio_route(adev, usecase);
2689 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 }
2691
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002692 /* Applicable only on the targets that has external modem.
2693 * New device information should be sent to modem before enabling
2694 * the devices to reduce in-call device switch time.
2695 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002696 if ((usecase->type == VOICE_CALL) &&
2697 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2698 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002699 status = platform_switch_voice_call_enable_device_config(adev->platform,
2700 out_snd_device,
2701 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002702 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002703
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002704 /* Enable new sound devices */
2705 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002706 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302707 if (platform_check_codec_asrc_support(adev->platform))
2708 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002709 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 }
2711
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002712 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302713 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002714 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002715 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002716
Avinash Vaish71a8b972014-07-24 15:36:33 +05302717 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002718 status = platform_switch_voice_call_device_post(adev->platform,
2719 out_snd_device,
2720 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302721 enable_audio_route_for_voice_usecases(adev, usecase);
2722 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002723
sangwoo170731f2013-06-08 15:36:36 +09002724 usecase->in_snd_device = in_snd_device;
2725 usecase->out_snd_device = out_snd_device;
2726
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302727 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2728 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302729 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002730 if ((24 == usecase->stream.out->bit_width) &&
2731 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2732 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2733 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2734 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2735 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2736 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2737 /*
2738 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2739 * configured device sample rate, if not update the COPP rate to be equal to the
2740 * device sample rate, else open COPP at stream sample rate
2741 */
2742 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2743 usecase->stream.out->sample_rate,
2744 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302745 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawate3af5102019-09-30 14:39:47 +05302746 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2747 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302748 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002749 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2750 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2751 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2752 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002753 }
2754 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002755
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002756 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002757
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002758 /* If input stream is already running then effect needs to be
2759 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002760 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002761 check_and_enable_effect(adev);
2762
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002763 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002764 /* Enable aanc only if voice call exists */
2765 if (voice_is_call_state_active(adev))
2766 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2767
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002768 /* Enable sidetone only if other voice/voip call already exists */
2769 if (voice_is_call_state_active(adev) ||
2770 voice_extn_compress_voip_is_started(adev))
2771 voice_set_sidetone(adev, out_snd_device, true);
2772 }
2773
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002774 /* Applicable only on the targets that has external modem.
2775 * Enable device command should be sent to modem only after
2776 * enabling voice call mixer controls
2777 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002778 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002779 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2780 out_snd_device,
2781 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302782
2783 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002784 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302785 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002786 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302787 if (is_bt_soc_on(adev) == false){
2788 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002789 if (in->pcm != NULL)
2790 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302791 }
2792 }
2793 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2794 && usecase->stream.out->started) {
2795 if (is_bt_soc_on(adev) == false) {
2796 ALOGD("BT SCO/A2DP disconnected while in connection");
2797 out_standby_l(&usecase->stream.out->stream.common);
2798 }
2799 }
2800 } else if ((usecase->stream.out != NULL) &&
2801 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302802 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2803 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0791c8e2019-07-25 13:18:17 +08002804 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302805 usecase->stream.out->started) {
2806 if (is_bt_soc_on(adev) == false) {
2807 ALOGD("BT SCO/A2dp disconnected while in connection");
2808 out_standby_l(&usecase->stream.out->stream.common);
2809 }
2810 }
2811 }
2812
Yung Ti Su70cb8242018-06-22 17:38:47 +08002813 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002814 struct stream_out *voip_out = voip_usecase->stream.out;
2815 audio_extn_utils_send_app_type_gain(adev,
2816 voip_out->app_type_cfg.app_type,
2817 &voip_out->app_type_cfg.gain[0]);
2818 }
2819
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302820 ALOGD("%s: done",__func__);
2821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822 return status;
2823}
2824
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825static int stop_input_stream(struct stream_in *in)
2826{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302827 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002828 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302829
2830 if (in == NULL) {
2831 ALOGE("%s: stream_in ptr is NULL", __func__);
2832 return -EINVAL;
2833 }
2834
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002835 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002836 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837
Eric Laurent994a6932013-07-17 11:51:42 -07002838 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002839 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002840 uc_info = get_usecase_from_list(adev, in->usecase);
2841 if (uc_info == NULL) {
2842 ALOGE("%s: Could not find the usecase (%d) in the list",
2843 __func__, in->usecase);
2844 return -EINVAL;
2845 }
2846
Carter Hsu2e429db2019-05-14 18:50:52 +08002847 priority_in = get_priority_input(adev);
2848
Derek Chenea197282019-01-07 17:35:01 -08002849 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2850 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002851
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002852 /* Close in-call recording streams */
2853 voice_check_and_stop_incall_rec_usecase(adev, in);
2854
Eric Laurent150dbfe2013-02-27 14:31:02 -08002855 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002856 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002857
2858 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002859 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002860
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05302861 if (is_loopback_input_device(in->device))
2862 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
2863
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002864 list_remove(&uc_info->list);
2865 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002866
Carter Hsu2e429db2019-05-14 18:50:52 +08002867 if (priority_in == in) {
2868 priority_in = get_priority_input(adev);
2869 if (priority_in)
2870 select_devices(adev, priority_in->usecase);
2871 }
2872
Vatsal Buchac09ae062018-11-14 13:25:08 +05302873 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002874 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002875 return ret;
2876}
2877
2878int start_input_stream(struct stream_in *in)
2879{
2880 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002881 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302883
2884 if (in == NULL) {
2885 ALOGE("%s: stream_in ptr is NULL", __func__);
2886 return -EINVAL;
2887 }
2888
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002890 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002891 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002892
Mingming Yin2664a5b2015-09-03 10:53:11 -07002893 if (get_usecase_from_list(adev, usecase) == NULL)
2894 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302895 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2896 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002897
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302898 if (CARD_STATUS_OFFLINE == in->card_status||
2899 CARD_STATUS_OFFLINE == adev->card_status) {
2900 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302901 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302902 goto error_config;
2903 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302904
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302905 if (audio_is_bluetooth_sco_device(in->device)) {
2906 if (!adev->bt_sco_on) {
2907 ALOGE("%s: SCO profile is not ready, return error", __func__);
2908 ret = -EIO;
2909 goto error_config;
2910 }
2911 }
2912
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002913 /* Check if source matches incall recording usecase criteria */
2914 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2915 if (ret)
2916 goto error_config;
2917 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002918 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2919
2920 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2921 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2922 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002923 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002924 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002925
Eric Laurentb23d5282013-05-14 15:27:20 -07002926 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002927 if (in->pcm_device_id < 0) {
2928 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2929 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002930 ret = -EINVAL;
2931 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002932 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002933
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002935
2936 if (!uc_info) {
2937 ret = -ENOMEM;
2938 goto error_config;
2939 }
2940
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002941 uc_info->id = in->usecase;
2942 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002943 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002944 uc_info->devices = in->device;
2945 uc_info->in_snd_device = SND_DEVICE_NONE;
2946 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002947
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002948 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002949 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302950 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2951 adev->perf_lock_opts,
2952 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002953 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002954
Derek Chenea197282019-01-07 17:35:01 -08002955 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2956 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002957
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05302958 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
2959
Haynes Mathew George16081042017-05-31 17:16:49 -07002960 if (audio_extn_cin_attached_usecase(in->usecase)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05302961 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302962 if (ret)
2963 goto error_open;
2964 else
2965 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002966 }
2967
Haynes Mathew George16081042017-05-31 17:16:49 -07002968 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002969 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002970 ALOGE("%s: pcm stream not ready", __func__);
2971 goto error_open;
2972 }
2973 ret = pcm_start(in->pcm);
2974 if (ret < 0) {
2975 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2976 goto error_open;
2977 }
2978 } else {
2979 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2980 unsigned int pcm_open_retry_count = 0;
2981
2982 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2983 flags |= PCM_MMAP | PCM_NOIRQ;
2984 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2985 } else if (in->realtime) {
2986 flags |= PCM_MMAP | PCM_NOIRQ;
2987 }
2988
Garmond Leunge2433c32017-09-28 21:51:22 -07002989 if (audio_extn_ffv_get_stream() == in) {
2990 ALOGD("%s: ffv stream, update pcm config", __func__);
2991 audio_extn_ffv_update_pcm_config(&config);
2992 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002993 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2994 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2995
2996 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002997 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002998 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002999 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003000 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303001 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303002 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3003 adev->card_status = CARD_STATUS_OFFLINE;
3004 in->card_status = CARD_STATUS_OFFLINE;
3005 ret = -EIO;
3006 goto error_open;
3007 }
3008
Haynes Mathew George16081042017-05-31 17:16:49 -07003009 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3010 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3011 if (in->pcm != NULL) {
3012 pcm_close(in->pcm);
3013 in->pcm = NULL;
3014 }
3015 if (pcm_open_retry_count-- == 0) {
3016 ret = -EIO;
3017 goto error_open;
3018 }
3019 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3020 continue;
3021 }
3022 break;
3023 }
3024
3025 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003026 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003027 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003028 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003029 if (ret < 0) {
3030 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3031 pcm_close(in->pcm);
3032 in->pcm = NULL;
3033 goto error_open;
3034 }
3035 register_in_stream(in);
3036 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003037 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003038 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003039 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003040 if (ret < 0) {
3041 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003042 pcm_close(in->pcm);
3043 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003044 goto error_open;
3045 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003046 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003047 }
3048
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003049 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003050 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3051 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003052
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303053 if (is_loopback_input_device(in->device))
3054 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3055
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303056done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003057 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303058 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003059 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303060 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003061 return ret;
3062
3063error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003064 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303065 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003066 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003067
Eric Laurentc8400632013-02-14 19:04:54 -08003068error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303069 /*
3070 * sleep 50ms to allow sufficient time for kernel
3071 * drivers to recover incases like SSR.
3072 */
3073 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003074 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303075 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003076 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003077}
3078
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003079void lock_input_stream(struct stream_in *in)
3080{
3081 pthread_mutex_lock(&in->pre_lock);
3082 pthread_mutex_lock(&in->lock);
3083 pthread_mutex_unlock(&in->pre_lock);
3084}
3085
3086void lock_output_stream(struct stream_out *out)
3087{
3088 pthread_mutex_lock(&out->pre_lock);
3089 pthread_mutex_lock(&out->lock);
3090 pthread_mutex_unlock(&out->pre_lock);
3091}
3092
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003093/* must be called with out->lock locked */
3094static int send_offload_cmd_l(struct stream_out* out, int command)
3095{
3096 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3097
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003098 if (!cmd) {
3099 ALOGE("failed to allocate mem for command 0x%x", command);
3100 return -ENOMEM;
3101 }
3102
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003103 ALOGVV("%s %d", __func__, command);
3104
3105 cmd->cmd = command;
3106 list_add_tail(&out->offload_cmd_list, &cmd->node);
3107 pthread_cond_signal(&out->offload_cond);
3108 return 0;
3109}
3110
3111/* must be called iwth out->lock locked */
3112static void stop_compressed_output_l(struct stream_out *out)
3113{
3114 out->offload_state = OFFLOAD_STATE_IDLE;
3115 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003116 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003117 if (out->compr != NULL) {
3118 compress_stop(out->compr);
3119 while (out->offload_thread_blocked) {
3120 pthread_cond_wait(&out->cond, &out->lock);
3121 }
3122 }
3123}
3124
Varun Balaraje49253e2017-07-06 19:48:56 +05303125bool is_interactive_usecase(audio_usecase_t uc_id)
3126{
3127 unsigned int i;
3128 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3129 if (uc_id == interactive_usecases[i])
3130 return true;
3131 }
3132 return false;
3133}
3134
3135static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3136{
3137 audio_usecase_t ret_uc = USECASE_INVALID;
3138 unsigned int intract_uc_index;
3139 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3140
3141 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3142 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3143 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3144 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3145 ret_uc = interactive_usecases[intract_uc_index];
3146 break;
3147 }
3148 }
3149
3150 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3151 return ret_uc;
3152}
3153
3154static void free_interactive_usecase(struct audio_device *adev,
3155 audio_usecase_t uc_id)
3156{
3157 unsigned int interact_uc_index;
3158 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3159
3160 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3161 if (interactive_usecases[interact_uc_index] == uc_id) {
3162 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3163 break;
3164 }
3165 }
3166 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3167}
3168
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003169bool is_offload_usecase(audio_usecase_t uc_id)
3170{
3171 unsigned int i;
3172 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3173 if (uc_id == offload_usecases[i])
3174 return true;
3175 }
3176 return false;
3177}
3178
Dhananjay Kumarac341582017-02-23 23:42:25 +05303179static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003180{
vivek mehta446c3962015-09-14 10:57:35 -07003181 audio_usecase_t ret_uc = USECASE_INVALID;
3182 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003183 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003184 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303185 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003186 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3187 else
3188 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003189
vivek mehta446c3962015-09-14 10:57:35 -07003190 pthread_mutex_lock(&adev->lock);
3191 if (get_usecase_from_list(adev, ret_uc) != NULL)
3192 ret_uc = USECASE_INVALID;
3193 pthread_mutex_unlock(&adev->lock);
3194
3195 return ret_uc;
3196 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003197
3198 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003199 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3200 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3201 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3202 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003203 break;
3204 }
3205 }
vivek mehta446c3962015-09-14 10:57:35 -07003206
3207 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3208 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003209}
3210
3211static void free_offload_usecase(struct audio_device *adev,
3212 audio_usecase_t uc_id)
3213{
vivek mehta446c3962015-09-14 10:57:35 -07003214 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003215 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003216
3217 if (!adev->multi_offload_enable)
3218 return;
3219
3220 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3221 if (offload_usecases[offload_uc_index] == uc_id) {
3222 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003223 break;
3224 }
3225 }
3226 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3227}
3228
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003229static void *offload_thread_loop(void *context)
3230{
3231 struct stream_out *out = (struct stream_out *) context;
3232 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003233 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003234
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003235 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangebfa0502019-07-18 17:24:21 +08003236 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003237 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3238
3239 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003240 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003241 out->offload_state = OFFLOAD_STATE_IDLE;
3242 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003243 for (;;) {
3244 struct offload_cmd *cmd = NULL;
3245 stream_callback_event_t event;
3246 bool send_callback = false;
3247
3248 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3249 __func__, list_empty(&out->offload_cmd_list),
3250 out->offload_state);
3251 if (list_empty(&out->offload_cmd_list)) {
3252 ALOGV("%s SLEEPING", __func__);
3253 pthread_cond_wait(&out->offload_cond, &out->lock);
3254 ALOGV("%s RUNNING", __func__);
3255 continue;
3256 }
3257
3258 item = list_head(&out->offload_cmd_list);
3259 cmd = node_to_item(item, struct offload_cmd, node);
3260 list_remove(item);
3261
3262 ALOGVV("%s STATE %d CMD %d out->compr %p",
3263 __func__, out->offload_state, cmd->cmd, out->compr);
3264
3265 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3266 free(cmd);
3267 break;
3268 }
3269
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003270 // allow OFFLOAD_CMD_ERROR reporting during standby
3271 // this is needed to handle failures during compress_open
3272 // Note however that on a pause timeout, the stream is closed
3273 // and no offload usecase will be active. Therefore this
3274 // special case is needed for compress_open failures alone
3275 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3276 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003277 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003278 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003279 pthread_cond_signal(&out->cond);
3280 continue;
3281 }
3282 out->offload_thread_blocked = true;
3283 pthread_mutex_unlock(&out->lock);
3284 send_callback = false;
3285 switch(cmd->cmd) {
3286 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003287 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003288 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003289 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003290 send_callback = true;
3291 event = STREAM_CBK_EVENT_WRITE_READY;
3292 break;
3293 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003294 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303295 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003296 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303297 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003298 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303299 if (ret < 0)
3300 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303301 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303302 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003303 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003304 else
3305 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003306 if (-ENETRESET != ret && !(-EINTR == ret &&
3307 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303308 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303309 pthread_mutex_lock(&out->lock);
3310 out->send_new_metadata = 1;
3311 out->send_next_track_params = true;
3312 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303313 event = STREAM_CBK_EVENT_DRAIN_READY;
3314 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3315 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303316 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003317 break;
3318 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003319 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003320 ret = compress_drain(out->compr);
3321 ALOGD("copl(%p):out of compress_drain", out);
3322 // EINTR check avoids drain interruption due to SSR
3323 if (-ENETRESET != ret && !(-EINTR == ret &&
3324 CARD_STATUS_OFFLINE == out->card_status)) {
3325 send_callback = true;
3326 event = STREAM_CBK_EVENT_DRAIN_READY;
3327 } else
3328 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003329 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303330 case OFFLOAD_CMD_ERROR:
3331 ALOGD("copl(%p): sending error callback to AF", out);
3332 send_callback = true;
3333 event = STREAM_CBK_EVENT_ERROR;
3334 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003335 default:
3336 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3337 break;
3338 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003339 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003340 out->offload_thread_blocked = false;
3341 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003342 if (send_callback && out->client_callback) {
3343 ALOGVV("%s: sending client_callback event %d", __func__, event);
3344 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003345 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003346 free(cmd);
3347 }
3348
3349 pthread_cond_signal(&out->cond);
3350 while (!list_empty(&out->offload_cmd_list)) {
3351 item = list_head(&out->offload_cmd_list);
3352 list_remove(item);
3353 free(node_to_item(item, struct offload_cmd, node));
3354 }
3355 pthread_mutex_unlock(&out->lock);
3356
3357 return NULL;
3358}
3359
3360static int create_offload_callback_thread(struct stream_out *out)
3361{
3362 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3363 list_init(&out->offload_cmd_list);
3364 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3365 offload_thread_loop, out);
3366 return 0;
3367}
3368
3369static int destroy_offload_callback_thread(struct stream_out *out)
3370{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003371 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003372 stop_compressed_output_l(out);
3373 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3374
3375 pthread_mutex_unlock(&out->lock);
3376 pthread_join(out->offload_thread, (void **) NULL);
3377 pthread_cond_destroy(&out->offload_cond);
3378
3379 return 0;
3380}
3381
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382static int stop_output_stream(struct stream_out *out)
3383{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303384 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003385 struct audio_usecase *uc_info;
3386 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003387 bool has_voip_usecase =
3388 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389
Eric Laurent994a6932013-07-17 11:51:42 -07003390 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003391 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003392 uc_info = get_usecase_from_list(adev, out->usecase);
3393 if (uc_info == NULL) {
3394 ALOGE("%s: Could not find the usecase (%d) in the list",
3395 __func__, out->usecase);
3396 return -EINVAL;
3397 }
3398
Derek Chenea197282019-01-07 17:35:01 -08003399 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3400 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003401
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003402 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303403 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003404 if (adev->visualizer_stop_output != NULL)
3405 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003406
3407 audio_extn_dts_remove_state_notifier_node(out->usecase);
3408
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003409 if (adev->offload_effects_stop_output != NULL)
3410 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003411 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3412 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3413 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003414 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003415
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003416 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3417 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003418 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003419 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003420
Eric Laurent150dbfe2013-02-27 14:31:02 -08003421 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003422 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003423
3424 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003425 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003426
Aalique Grahame22e49102018-12-18 14:23:57 -08003427 audio_extn_extspk_update(adev->extspk);
3428
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003429 if (is_offload_usecase(out->usecase)) {
3430 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3431 adev->dsp_bit_width_enforce_mode,
3432 false);
3433 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003434 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3435 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3436 false);
3437
3438 if (ret != 0)
3439 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3440 /* default service interval was successfully updated,
3441 reopen USB backend with new service interval */
3442 ret = 0;
3443 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003444
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003445 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303446 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003447 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303448 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003449 ALOGV("Disable passthrough , reset mixer to pcm");
3450 /* NO_PASSTHROUGH */
3451 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003452 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003453 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3454 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003455
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303456 /* Must be called after removing the usecase from list */
3457 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303458 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303459
Manish Dewangan21a850a2017-08-14 12:03:55 +05303460 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003461 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3462 if (ret < 0)
3463 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3464 }
3465
juyuchen2d415992018-11-16 14:15:16 +08003466 /* 1) media + voip output routing to handset must route media back to
3467 speaker when voip stops.
3468 2) trigger voip input to reroute when voip output changes to
3469 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003470 if (has_voip_usecase ||
3471 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3472 struct listnode *node;
3473 struct audio_usecase *usecase;
3474 list_for_each(node, &adev->usecase_list) {
3475 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003476 if ((usecase->type == PCM_CAPTURE &&
3477 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3478 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003479 continue;
3480
3481 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3482 __func__, usecase->id, use_case_table[usecase->id],
3483 out->usecase, use_case_table[out->usecase]);
3484 select_devices(adev, usecase->id);
3485 }
3486 }
3487
Garmond Leung5fd0b552018-04-17 11:56:12 -07003488 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003489 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003490 return ret;
3491}
3492
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003493struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3494 unsigned int flags, unsigned int pcm_open_retry_count,
3495 struct pcm_config *config)
3496{
3497 struct pcm* pcm = NULL;
3498
3499 while (1) {
3500 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3501 if (pcm == NULL || !pcm_is_ready(pcm)) {
3502 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3503 if (pcm != NULL) {
3504 pcm_close(pcm);
3505 pcm = NULL;
3506 }
3507 if (pcm_open_retry_count-- == 0)
3508 return NULL;
3509
3510 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3511 continue;
3512 }
3513 break;
3514 }
3515
3516 if (pcm_is_ready(pcm)) {
3517 int ret = pcm_prepare(pcm);
3518 if (ret < 0) {
3519 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3520 pcm_close(pcm);
3521 pcm = NULL;
3522 }
3523 }
3524
3525 return pcm;
3526}
3527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528int start_output_stream(struct stream_out *out)
3529{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 struct audio_usecase *uc_info;
3532 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003533 char mixer_ctl_name[128];
3534 struct mixer_ctl *ctl = NULL;
3535 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303536 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003537 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003538
Haynes Mathew George380745d2017-10-04 15:27:45 -07003539 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003540 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3541 ret = -EINVAL;
3542 goto error_config;
3543 }
3544
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003545 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303546 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003547 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303548
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303549 if (CARD_STATUS_OFFLINE == out->card_status ||
3550 CARD_STATUS_OFFLINE == adev->card_status) {
3551 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303552 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303553 goto error_config;
3554 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303555
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003556 //Update incall music usecase to reflect correct voice session
3557 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3558 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3559 if (ret != 0) {
3560 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3561 __func__, ret);
3562 goto error_config;
3563 }
3564 }
3565
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303566 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003567 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003568 if (out->devices &
3569 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303570 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303571 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303572 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3573 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3574 ret = -EAGAIN;
3575 goto error_config;
3576 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303577 }
3578 }
3579 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303580 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3581 if (!adev->bt_sco_on) {
3582 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3583 //combo usecase just by pass a2dp
3584 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3585 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3586 } else {
3587 ALOGE("%s: SCO profile is not ready, return error", __func__);
3588 ret = -EAGAIN;
3589 goto error_config;
3590 }
3591 }
3592 }
3593
Eric Laurentb23d5282013-05-14 15:27:20 -07003594 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003595 if (out->pcm_device_id < 0) {
3596 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3597 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003598 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003599 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003600 }
3601
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003602 if (is_haptic_usecase) {
3603 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3604 if (adev->haptic_pcm_device_id < 0) {
3605 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3606 __func__, adev->haptic_pcm_device_id, out->usecase);
3607 ret = -EINVAL;
3608 goto error_config;
3609 }
3610 }
3611
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003613
3614 if (!uc_info) {
3615 ret = -ENOMEM;
3616 goto error_config;
3617 }
3618
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003619 uc_info->id = out->usecase;
3620 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003621 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003622 uc_info->devices = out->devices;
3623 uc_info->in_snd_device = SND_DEVICE_NONE;
3624 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003625
3626 /* This must be called before adding this usecase to the list */
3627 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3628 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3629 /* USB backend is not reopened immediately.
3630 This is eventually done as part of select_devices */
3631 }
3632
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003633 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003634
Wei Wangf7ca6c92017-11-21 14:51:20 -08003635 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303636 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3637 adev->perf_lock_opts,
3638 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303639
3640 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303641 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303642 if (audio_extn_passthru_is_enabled() &&
3643 audio_extn_passthru_is_passthrough_stream(out)) {
3644 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303645 }
3646 }
3647
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303648 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003649 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303650 if (!a2dp_combo) {
3651 check_a2dp_restore_l(adev, out, false);
3652 } else {
3653 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003654 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3655 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3656 else
3657 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303658 select_devices(adev, out->usecase);
3659 out->devices = dev;
3660 }
3661 } else {
3662 select_devices(adev, out->usecase);
3663 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003664
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003665 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3666 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003667 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003668 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003669
Derek Chenea197282019-01-07 17:35:01 -08003670 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3671 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003672
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003673 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3674 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003675
3676 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003677 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003678 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3679 ALOGE("%s: pcm stream not ready", __func__);
3680 goto error_open;
3681 }
3682 ret = pcm_start(out->pcm);
3683 if (ret < 0) {
3684 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3685 goto error_open;
3686 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003687 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003688 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003689 unsigned int flags = PCM_OUT;
3690 unsigned int pcm_open_retry_count = 0;
3691 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3692 flags |= PCM_MMAP | PCM_NOIRQ;
3693 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003694 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003695 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003696 } else
3697 flags |= PCM_MONOTONIC;
3698
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003699 if ((adev->vr_audio_mode_enabled) &&
3700 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3701 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3702 "PCM_Dev %d Topology", out->pcm_device_id);
3703 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3704 if (!ctl) {
3705 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3706 __func__, mixer_ctl_name);
3707 } else {
3708 //if success use ULLPP
3709 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3710 __func__, mixer_ctl_name, out->pcm_device_id);
3711 //There is a still a possibility that some sessions
3712 // that request for FAST|RAW when 3D audio is active
3713 //can go through ULLPP. Ideally we expects apps to
3714 //listen to audio focus and stop concurrent playback
3715 //Also, we will look for mode flag (voice_in_communication)
3716 //before enabling the realtime flag.
3717 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3718 }
3719 }
3720
Surendar Karka91fa3682018-07-02 18:12:12 +05303721 if (out->realtime)
3722 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3723 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3724
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003725 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3726 flags, pcm_open_retry_count,
3727 &(out->config));
3728 if (out->pcm == NULL) {
3729 ret = -EIO;
3730 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003731 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003732
3733 if (is_haptic_usecase) {
3734 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3735 adev->haptic_pcm_device_id,
3736 flags, pcm_open_retry_count,
3737 &(adev->haptics_config));
3738 // failure to open haptics pcm shouldnt stop audio,
3739 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003740
3741 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3742 ALOGD("%s: enable haptic audio synchronization", __func__);
3743 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3744 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003745 }
3746
Surendar Karka91fa3682018-07-02 18:12:12 +05303747 if (!out->realtime)
3748 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303749 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003750
Zhou Song2b8f28f2017-09-11 10:51:38 +08003751 // apply volume for voip playback after path is set up
3752 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3753 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303754 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3755 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303756 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3757 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003758 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3759 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303760 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003761 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003762 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303763 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003764 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3765 adev->dsp_bit_width_enforce_mode,
3766 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003767 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003768 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003769 out->compr = compress_open(adev->snd_card,
3770 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003771 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003772 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303773 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303774 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3775 adev->card_status = CARD_STATUS_OFFLINE;
3776 out->card_status = CARD_STATUS_OFFLINE;
3777 ret = -EIO;
3778 goto error_open;
3779 }
3780
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003781 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003782 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003783 compress_close(out->compr);
3784 out->compr = NULL;
3785 ret = -EIO;
3786 goto error_open;
3787 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303788 /* compress_open sends params of the track, so reset the flag here */
3789 out->is_compr_metadata_avail = false;
3790
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003791 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003792 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003793
Fred Oh3f43e742015-03-04 18:42:34 -08003794 /* Since small bufs uses blocking writes, a write will be blocked
3795 for the default max poll time (20s) in the event of an SSR.
3796 Reduce the poll time to observe and deal with SSR faster.
3797 */
Ashish Jain5106d362016-05-11 19:23:33 +05303798 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003799 compress_set_max_poll_wait(out->compr, 1000);
3800 }
3801
Manish Dewangan69426c82017-01-30 17:35:36 +05303802 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303803 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303804
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003805 audio_extn_dts_create_state_notifier_node(out->usecase);
3806 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3807 popcount(out->channel_mask),
3808 out->playback_started);
3809
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003810#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303811 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003812 audio_extn_dolby_send_ddp_endp_params(adev);
3813#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303814 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3815 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003816 if (adev->visualizer_start_output != NULL)
3817 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3818 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303819 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003820 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003821 }
Derek Chenf13dd492018-11-13 14:53:51 -08003822
3823 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
3824 /* Update cached volume from media to offload/direct stream */
3825 struct listnode *node = NULL;
3826 list_for_each(node, &adev->active_outputs_list) {
3827 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3828 streams_output_ctxt_t,
3829 list);
3830 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3831 out->volume_l = out_ctxt->output->volume_l;
3832 out->volume_r = out_ctxt->output->volume_r;
3833 }
3834 }
3835 out_set_compr_volume(&out->stream,
3836 out->volume_l, out->volume_r);
3837 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003838 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003839
3840 if (ret == 0) {
3841 register_out_stream(out);
3842 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003843 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3844 ALOGE("%s: pcm stream not ready", __func__);
3845 goto error_open;
3846 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003847 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003848 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003849 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003850 if (ret < 0)
3851 goto error_open;
3852 }
3853 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003854 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303855 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003856 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003857
vivek mehtad15d2bf2019-05-17 13:35:10 -07003858 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3859 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3860 audio_low_latency_hint_start();
3861 }
3862
Manish Dewangan21a850a2017-08-14 12:03:55 +05303863 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003864 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003865 if (ret < 0)
3866 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3867 }
3868
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003869 // consider a scenario where on pause lower layers are tear down.
3870 // so on resume, swap mixer control need to be sent only when
3871 // backend is active, hence rather than sending from enable device
3872 // sending it from start of streamtream
3873
3874 platform_set_swap_channels(adev, true);
3875
Haynes Mathew George380745d2017-10-04 15:27:45 -07003876 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303877 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003878 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003879error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003880 if (adev->haptic_pcm) {
3881 pcm_close(adev->haptic_pcm);
3882 adev->haptic_pcm = NULL;
3883 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003884 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303885 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003886 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003887error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303888 /*
3889 * sleep 50ms to allow sufficient time for kernel
3890 * drivers to recover incases like SSR.
3891 */
3892 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003893 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303894 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003895 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003896}
3897
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898static int check_input_parameters(uint32_t sample_rate,
3899 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003900 int channel_count,
3901 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003902{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003903 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303905 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3906 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3907 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003908 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003909 !audio_extn_compr_cap_format_supported(format) &&
3910 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003911 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003912
Aalique Grahame22e49102018-12-18 14:23:57 -08003913 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3914 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3915 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3916 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3917 return -EINVAL;
3918 }
3919
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003920 switch (channel_count) {
3921 case 1:
3922 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303923 case 3:
3924 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003925 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003926 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303927 case 10:
3928 case 12:
3929 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003930 break;
3931 default:
3932 ret = -EINVAL;
3933 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003934
3935 switch (sample_rate) {
3936 case 8000:
3937 case 11025:
3938 case 12000:
3939 case 16000:
3940 case 22050:
3941 case 24000:
3942 case 32000:
3943 case 44100:
3944 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003945 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303946 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003947 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303948 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 break;
3950 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003951 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952 }
3953
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003954 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003955}
3956
Naresh Tanniru04f71882018-06-26 17:46:22 +05303957
3958/** Add a value in a list if not already present.
3959 * @return true if value was successfully inserted or already present,
3960 * false if the list is full and does not contain the value.
3961 */
3962static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3963 for (size_t i = 0; i < list_length; i++) {
3964 if (list[i] == value) return true; // value is already present
3965 if (list[i] == 0) { // no values in this slot
3966 list[i] = value;
3967 return true; // value inserted
3968 }
3969 }
3970 return false; // could not insert value
3971}
3972
3973/** Add channel_mask in supported_channel_masks if not already present.
3974 * @return true if channel_mask was successfully inserted or already present,
3975 * false if supported_channel_masks is full and does not contain channel_mask.
3976 */
3977static void register_channel_mask(audio_channel_mask_t channel_mask,
3978 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3979 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3980 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3981}
3982
3983/** Add format in supported_formats if not already present.
3984 * @return true if format was successfully inserted or already present,
3985 * false if supported_formats is full and does not contain format.
3986 */
3987static void register_format(audio_format_t format,
3988 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3989 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3990 "%s: stream can not declare supporting its format %x", __func__, format);
3991}
3992/** Add sample_rate in supported_sample_rates if not already present.
3993 * @return true if sample_rate was successfully inserted or already present,
3994 * false if supported_sample_rates is full and does not contain sample_rate.
3995 */
3996static void register_sample_rate(uint32_t sample_rate,
3997 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3998 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3999 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4000}
4001
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004002static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4003{
4004 uint32_t high = num1, low = num2, temp = 0;
4005
4006 if (!num1 || !num2)
4007 return 0;
4008
4009 if (num1 < num2) {
4010 high = num2;
4011 low = num1;
4012 }
4013
4014 while (low != 0) {
4015 temp = low;
4016 low = high % low;
4017 high = temp;
4018 }
4019 return (num1 * num2)/high;
4020}
4021
4022static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4023{
4024 uint32_t remainder = 0;
4025
4026 if (!multiplier)
4027 return num;
4028
4029 remainder = num % multiplier;
4030 if (remainder)
4031 num += (multiplier - remainder);
4032
4033 return num;
4034}
4035
Aalique Grahame22e49102018-12-18 14:23:57 -08004036static size_t get_stream_buffer_size(size_t duration_ms,
4037 uint32_t sample_rate,
4038 audio_format_t format,
4039 int channel_count,
4040 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041{
4042 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004043 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004044
Aalique Grahame22e49102018-12-18 14:23:57 -08004045 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004046 if (is_low_latency)
4047 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304048
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004049 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004050 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004051
Ralf Herzbd08d632018-09-28 15:50:49 +02004052 /* make sure the size is multiple of 32 bytes and additionally multiple of
4053 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004054 * At 48 kHz mono 16-bit PCM:
4055 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4056 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004057 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004058 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004059 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004060
4061 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004062}
4063
Aalique Grahame22e49102018-12-18 14:23:57 -08004064static size_t get_input_buffer_size(uint32_t sample_rate,
4065 audio_format_t format,
4066 int channel_count,
4067 bool is_low_latency)
4068{
4069 /* Don't know if USB HIFI in this context so use true to be conservative */
4070 if (check_input_parameters(sample_rate, format, channel_count,
4071 true /*is_usb_hifi */) != 0)
4072 return 0;
4073
4074 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4075 sample_rate,
4076 format,
4077 channel_count,
4078 is_low_latency);
4079}
4080
Derek Chenf6318be2017-06-12 17:16:24 -04004081size_t get_output_period_size(uint32_t sample_rate,
4082 audio_format_t format,
4083 int channel_count,
4084 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304085{
4086 size_t size = 0;
4087 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4088
4089 if ((duration == 0) || (sample_rate == 0) ||
4090 (bytes_per_sample == 0) || (channel_count == 0)) {
4091 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4092 bytes_per_sample, channel_count);
4093 return -EINVAL;
4094 }
4095
4096 size = (sample_rate *
4097 duration *
4098 bytes_per_sample *
4099 channel_count) / 1000;
4100 /*
4101 * To have same PCM samples for all channels, the buffer size requires to
4102 * be multiple of (number of channels * bytes per sample)
4103 * For writes to succeed, the buffer must be written at address which is multiple of 32
4104 */
4105 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4106
4107 return (size/(channel_count * bytes_per_sample));
4108}
4109
Zhou Song48453a02018-01-10 17:50:59 +08004110static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304111{
4112 uint64_t actual_frames_rendered = 0;
4113 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4114
4115 /* This adjustment accounts for buffering after app processor.
4116 * It is based on estimated DSP latency per use case, rather than exact.
4117 */
4118 int64_t platform_latency = platform_render_latency(out->usecase) *
4119 out->sample_rate / 1000000LL;
4120
Zhou Song48453a02018-01-10 17:50:59 +08004121 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304122 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4123 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4124 * hence only estimate.
4125 */
4126 int64_t signed_frames = out->written - kernel_buffer_size;
4127
4128 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
4129
Zhou Song48453a02018-01-10 17:50:59 +08004130 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304131 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004132 if (timestamp != NULL )
4133 *timestamp = out->writeAt;
4134 } else if (timestamp != NULL) {
4135 clock_gettime(CLOCK_MONOTONIC, timestamp);
4136 }
4137 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304138
4139 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
4140 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
4141 (long long int)out->written, (int)kernel_buffer_size,
4142 audio_bytes_per_sample(out->compr_config.codec->format),
4143 popcount(out->channel_mask));
4144
4145 return actual_frames_rendered;
4146}
4147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004148static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4149{
4150 struct stream_out *out = (struct stream_out *)stream;
4151
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004152 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004153}
4154
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004155static int out_set_sample_rate(struct audio_stream *stream __unused,
4156 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004157{
4158 return -ENOSYS;
4159}
4160
4161static size_t out_get_buffer_size(const struct audio_stream *stream)
4162{
4163 struct stream_out *out = (struct stream_out *)stream;
4164
Varun Balaraje49253e2017-07-06 19:48:56 +05304165 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304166 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304167 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304168 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4169 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4170 else
4171 return out->compr_config.fragment_size;
4172 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004173 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304174 else if (is_offload_usecase(out->usecase) &&
4175 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304176 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004177
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004178 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004179 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004180}
4181
4182static uint32_t out_get_channels(const struct audio_stream *stream)
4183{
4184 struct stream_out *out = (struct stream_out *)stream;
4185
4186 return out->channel_mask;
4187}
4188
4189static audio_format_t out_get_format(const struct audio_stream *stream)
4190{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004191 struct stream_out *out = (struct stream_out *)stream;
4192
4193 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194}
4195
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004196static int out_set_format(struct audio_stream *stream __unused,
4197 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004198{
4199 return -ENOSYS;
4200}
4201
4202static int out_standby(struct audio_stream *stream)
4203{
4204 struct stream_out *out = (struct stream_out *)stream;
4205 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004206 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004207
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304208 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4209 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004210
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004211 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004213 if (adev->adm_deregister_stream)
4214 adev->adm_deregister_stream(adev->adm_data, out->handle);
4215
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004216 if (is_offload_usecase(out->usecase))
4217 stop_compressed_output_l(out);
4218
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004219 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004220 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004221 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4222 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304223 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004224 pthread_mutex_unlock(&adev->lock);
4225 pthread_mutex_unlock(&out->lock);
4226 ALOGD("VOIP output entered standby");
4227 return 0;
4228 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004229 if (out->pcm) {
4230 pcm_close(out->pcm);
4231 out->pcm = NULL;
4232 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004233 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4234 do_stop = out->playback_started;
4235 out->playback_started = false;
4236 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004237 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004238 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304239 out->send_next_track_params = false;
4240 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004241 out->gapless_mdata.encoder_delay = 0;
4242 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004243 if (out->compr != NULL) {
4244 compress_close(out->compr);
4245 out->compr = NULL;
4246 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004247 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004248 if (do_stop) {
4249 stop_output_stream(out);
4250 }
Lakshman Chaluvaraju40459022019-06-24 10:04:52 +05304251 // if fm is active route on selected device in UI
4252 audio_extn_fm_route_on_selected_device(adev, out->devices);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004253 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254 }
4255 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304256 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004257 return 0;
4258}
4259
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304260static int out_on_error(struct audio_stream *stream)
4261{
4262 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004263 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304264
4265 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004266 // always send CMD_ERROR for offload streams, this
4267 // is needed e.g. when SSR happens within compress_open
4268 // since the stream is active, offload_callback_thread is also active.
4269 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4270 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004271 }
4272 pthread_mutex_unlock(&out->lock);
4273
4274 status = out_standby(&out->stream.common);
4275
4276 lock_output_stream(out);
4277 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004278 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304279 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304280
4281 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4282 ALOGD("Setting previous card status if offline");
4283 out->prev_card_status_offline = true;
4284 }
4285
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304286 pthread_mutex_unlock(&out->lock);
4287
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004288 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304289}
4290
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304291/*
4292 *standby implementation without locks, assumes that the callee already
4293 *has taken adev and out lock.
4294 */
4295int out_standby_l(struct audio_stream *stream)
4296{
4297 struct stream_out *out = (struct stream_out *)stream;
4298 struct audio_device *adev = out->dev;
4299
4300 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4301 stream, out->usecase, use_case_table[out->usecase]);
4302
4303 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004304 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304305 if (adev->adm_deregister_stream)
4306 adev->adm_deregister_stream(adev->adm_data, out->handle);
4307
4308 if (is_offload_usecase(out->usecase))
4309 stop_compressed_output_l(out);
4310
4311 out->standby = true;
4312 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4313 voice_extn_compress_voip_close_output_stream(stream);
4314 out->started = 0;
4315 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004316 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304317 return 0;
4318 } else if (!is_offload_usecase(out->usecase)) {
4319 if (out->pcm) {
4320 pcm_close(out->pcm);
4321 out->pcm = NULL;
4322 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004323 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4324 if (adev->haptic_pcm) {
4325 pcm_close(adev->haptic_pcm);
4326 adev->haptic_pcm = NULL;
4327 }
4328
4329 if (adev->haptic_buffer != NULL) {
4330 free(adev->haptic_buffer);
4331 adev->haptic_buffer = NULL;
4332 adev->haptic_buffer_size = 0;
4333 }
4334 adev->haptic_pcm_device_id = 0;
4335 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304336 } else {
4337 ALOGD("copl(%p):standby", out);
4338 out->send_next_track_params = false;
4339 out->is_compr_metadata_avail = false;
4340 out->gapless_mdata.encoder_delay = 0;
4341 out->gapless_mdata.encoder_padding = 0;
4342 if (out->compr != NULL) {
4343 compress_close(out->compr);
4344 out->compr = NULL;
4345 }
4346 }
4347 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004348 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304349 }
4350 ALOGD("%s: exit", __func__);
4351 return 0;
4352}
4353
Aalique Grahame22e49102018-12-18 14:23:57 -08004354static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004355{
Aalique Grahame22e49102018-12-18 14:23:57 -08004356 struct stream_out *out = (struct stream_out *)stream;
4357
4358 // We try to get the lock for consistency,
4359 // but it isn't necessary for these variables.
4360 // If we're not in standby, we may be blocked on a write.
4361 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4362 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4363 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4364
4365 if (locked) {
4366 pthread_mutex_unlock(&out->lock);
4367 }
4368
4369 // dump error info
4370 (void)error_log_dump(
4371 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4372
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004373 return 0;
4374}
4375
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004376static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4377{
4378 int ret = 0;
4379 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004380
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004381 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004382 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004383 return -EINVAL;
4384 }
4385
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304386 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004387
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004388 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4389 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304390 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004391 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004392 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4393 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304394 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004395 }
4396
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004397 ALOGV("%s new encoder delay %u and padding %u", __func__,
4398 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4399
4400 return 0;
4401}
4402
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004403static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4404{
4405 return out == adev->primary_output || out == adev->voice_tx_output;
4406}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004407
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304408// note: this call is safe only if the stream_cb is
4409// removed first in close_output_stream (as is done now).
4410static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4411{
4412 if (!stream || !parms)
4413 return;
4414
4415 struct stream_out *out = (struct stream_out *)stream;
4416 struct audio_device *adev = out->dev;
4417
4418 card_status_t status;
4419 int card;
4420 if (parse_snd_card_status(parms, &card, &status) < 0)
4421 return;
4422
4423 pthread_mutex_lock(&adev->lock);
4424 bool valid_cb = (card == adev->snd_card);
4425 pthread_mutex_unlock(&adev->lock);
4426
4427 if (!valid_cb)
4428 return;
4429
4430 lock_output_stream(out);
4431 if (out->card_status != status)
4432 out->card_status = status;
4433 pthread_mutex_unlock(&out->lock);
4434
4435 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4436 use_case_table[out->usecase],
4437 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4438
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304439 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304440 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304441 if (voice_is_call_state_active(adev) &&
4442 out == adev->primary_output) {
4443 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4444 pthread_mutex_lock(&adev->lock);
4445 voice_stop_call(adev);
4446 adev->mode = AUDIO_MODE_NORMAL;
4447 pthread_mutex_unlock(&adev->lock);
4448 }
4449 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304450 return;
4451}
4452
Kevin Rocardfce19002017-08-07 19:21:36 -07004453static int get_alive_usb_card(struct str_parms* parms) {
4454 int card;
4455 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4456 !audio_extn_usb_alive(card)) {
4457 return card;
4458 }
4459 return -ENODEV;
4460}
4461
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004462static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4463{
4464 struct stream_out *out = (struct stream_out *)stream;
4465 struct audio_device *adev = out->dev;
4466 struct str_parms *parms;
4467 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004468 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304469 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004470 bool reconfig = false;
4471 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004472
sangwoobc677242013-08-08 16:53:43 +09004473 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004474 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004475 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304476 if (!parms)
4477 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004478 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4479 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004481 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004482 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004483
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004484 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004485 * When HDMI cable is unplugged the music playback is paused and
4486 * the policy manager sends routing=0. But the audioflinger continues
4487 * to write data until standby time (3sec). As the HDMI core is
4488 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004489 * Avoid this by routing audio to speaker until standby.
4490 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004491 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4492 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304493 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004494 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4495 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004496 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304497 /*
4498 * When A2DP is disconnected the
4499 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004500 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304501 * (3sec). As BT is turned off, the write gets blocked.
4502 * Avoid this by routing audio to speaker until standby.
4503 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004504 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004505 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004506 !audio_extn_a2dp_source_is_ready() &&
4507 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304508 val = AUDIO_DEVICE_OUT_SPEAKER;
4509 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304510 /*
4511 * When USB headset is disconnected the music platback paused
4512 * and the policy manager send routing=0. But if the USB is connected
4513 * back before the standby time, AFE is not closed and opened
4514 * when USB is connected back. So routing to speker will guarantee
4515 * AFE reconfiguration and AFE will be opend once USB is connected again
4516 */
4517 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4518 (val == AUDIO_DEVICE_NONE) &&
4519 !audio_extn_usb_connected(parms)) {
4520 val = AUDIO_DEVICE_OUT_SPEAKER;
4521 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304522 /* To avoid a2dp to sco overlapping / BT device improper state
4523 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304524 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304525 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004526 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004527 if (val &
4528 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304529 //combo usecase just by pass a2dp
4530 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304531 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304532 } else {
4533 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4534 /* update device to a2dp and don't route as BT returned error
4535 * However it is still possible a2dp routing called because
4536 * of current active device disconnection (like wired headset)
4537 */
4538 out->devices = val;
4539 pthread_mutex_unlock(&out->lock);
4540 pthread_mutex_unlock(&adev->lock);
4541 goto error;
4542 }
4543 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304544 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004545
4546 audio_devices_t new_dev = val;
4547
4548 // Workaround: If routing to an non existing usb device, fail gracefully
4549 // The routing request will otherwise block during 10 second
4550 int card;
4551 if (audio_is_usb_out_device(new_dev) &&
4552 (card = get_alive_usb_card(parms)) >= 0) {
4553
4554 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4555 pthread_mutex_unlock(&adev->lock);
4556 pthread_mutex_unlock(&out->lock);
4557 ret = -ENOSYS;
4558 goto routing_fail;
4559 }
4560
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004561 /*
4562 * select_devices() call below switches all the usecases on the same
4563 * backend to the new device. Refer to check_usecases_codec_backend() in
4564 * the select_devices(). But how do we undo this?
4565 *
4566 * For example, music playback is active on headset (deep-buffer usecase)
4567 * and if we go to ringtones and select a ringtone, low-latency usecase
4568 * will be started on headset+speaker. As we can't enable headset+speaker
4569 * and headset devices at the same time, select_devices() switches the music
4570 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4571 * So when the ringtone playback is completed, how do we undo the same?
4572 *
4573 * We are relying on the out_set_parameters() call on deep-buffer output,
4574 * once the ringtone playback is ended.
4575 * NOTE: We should not check if the current devices are same as new devices.
4576 * Because select_devices() must be called to switch back the music
4577 * playback to headset.
4578 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004579 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004580 audio_devices_t new_dev = val;
4581 bool same_dev = out->devices == new_dev;
4582 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004583
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004584 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004585 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004586 if (adev->mode == AUDIO_MODE_IN_CALL) {
4587 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004588 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4589 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4590 audio_extn_usb_set_service_interval(true /*playback*/,
4591 service_interval,
4592 &reconfig);
4593 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4594 }
4595 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004596 }
4597 } else {
4598 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004599 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004600 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004601 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004602
4603 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004604 if (!same_dev) {
4605 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304606 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4607 adev->perf_lock_opts,
4608 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004609 if (adev->adm_on_routing_change)
4610 adev->adm_on_routing_change(adev->adm_data,
4611 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004612 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304613 if (!bypass_a2dp) {
4614 select_devices(adev, out->usecase);
4615 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004616 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4617 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4618 else
4619 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304620 select_devices(adev, out->usecase);
4621 out->devices = new_dev;
4622 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004623
4624 if (!same_dev) {
4625 // on device switch force swap, lower functions will make sure
4626 // to check if swap is allowed or not.
4627 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304628 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004629 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304630 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4631 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004632 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304633 pthread_mutex_lock(&out->compr_mute_lock);
4634 out->a2dp_compress_mute = false;
4635 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4636 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004637 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4638 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304639 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004640 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004641 }
4642
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004643 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004644 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004645
4646 /*handles device and call state changes*/
4647 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004648 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004649 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004650
4651 if (out == adev->primary_output) {
4652 pthread_mutex_lock(&adev->lock);
4653 audio_extn_set_parameters(adev, parms);
4654 pthread_mutex_unlock(&adev->lock);
4655 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004656 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004657 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004658 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004659
4660 audio_extn_dts_create_state_notifier_node(out->usecase);
4661 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4662 popcount(out->channel_mask),
4663 out->playback_started);
4664
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004665 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004666 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004667
Surendar Karkaf51b5842018-04-26 11:28:38 +05304668 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4669 sizeof(value));
4670 if (err >= 0) {
4671 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4672 audio_extn_send_dual_mono_mixing_coefficients(out);
4673 }
4674
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304675 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4676 if (err >= 0) {
4677 strlcpy(out->profile, value, sizeof(out->profile));
4678 ALOGV("updating stream profile with value '%s'", out->profile);
4679 lock_output_stream(out);
4680 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4681 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004682 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304683 out->sample_rate, out->bit_width,
4684 out->channel_mask, out->profile,
4685 &out->app_type_cfg);
4686 pthread_mutex_unlock(&out->lock);
4687 }
4688
Alexy Joseph98988832017-01-13 14:56:59 -08004689 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004690 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4691 // and vendor.audio.hal.output.suspend.supported is set to true
4692 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004693 //check suspend parameter only for low latency and if the property
4694 //is enabled
4695 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4696 ALOGI("%s: got suspend_playback %s", __func__, value);
4697 lock_output_stream(out);
4698 if (!strncmp(value, "false", 5)) {
4699 //suspend_playback=false is supposed to set QOS value back to 75%
4700 //the mixer control sent with value Enable will achieve that
4701 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4702 } else if (!strncmp (value, "true", 4)) {
4703 //suspend_playback=true is supposed to remove QOS value
4704 //resetting the mixer control will set the default value
4705 //for the mixer control which is Disable and this removes the QOS vote
4706 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4707 } else {
4708 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4709 " got %s", __func__, value);
4710 ret = -1;
4711 }
4712
4713 if (ret != 0) {
4714 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4715 __func__, out->pm_qos_mixer_path, ret);
4716 }
4717
4718 pthread_mutex_unlock(&out->lock);
4719 }
4720 }
4721 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004722 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304723error:
Eric Laurent994a6932013-07-17 11:51:42 -07004724 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004725 return ret;
4726}
4727
Paul McLeana50b7332018-12-17 08:24:21 -07004728static int in_set_microphone_direction(const struct audio_stream_in *stream,
4729 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004730 struct stream_in *in = (struct stream_in *)stream;
4731
4732 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4733
4734 in->direction = dir;
4735
4736 if (in->standby)
4737 return 0;
4738
4739 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004740}
4741
4742static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004743 struct stream_in *in = (struct stream_in *)stream;
4744
4745 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4746
4747 if (zoom > 1.0 || zoom < -1.0)
4748 return -EINVAL;
4749
4750 in->zoom = zoom;
4751
4752 if (in->standby)
4753 return 0;
4754
4755 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004756}
4757
4758
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004759static bool stream_get_parameter_channels(struct str_parms *query,
4760 struct str_parms *reply,
4761 audio_channel_mask_t *supported_channel_masks) {
4762 int ret = -1;
4763 char value[512];
4764 bool first = true;
4765 size_t i, j;
4766
4767 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4768 ret = 0;
4769 value[0] = '\0';
4770 i = 0;
4771 while (supported_channel_masks[i] != 0) {
4772 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4773 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4774 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304775 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004776
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304777 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004778 first = false;
4779 break;
4780 }
4781 }
4782 i++;
4783 }
4784 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4785 }
4786 return ret == 0;
4787}
4788
4789static bool stream_get_parameter_formats(struct str_parms *query,
4790 struct str_parms *reply,
4791 audio_format_t *supported_formats) {
4792 int ret = -1;
4793 char value[256];
4794 size_t i, j;
4795 bool first = true;
4796
4797 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4798 ret = 0;
4799 value[0] = '\0';
4800 i = 0;
4801 while (supported_formats[i] != 0) {
4802 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4803 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4804 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304805 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004806 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304807 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004808 first = false;
4809 break;
4810 }
4811 }
4812 i++;
4813 }
4814 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4815 }
4816 return ret == 0;
4817}
4818
4819static bool stream_get_parameter_rates(struct str_parms *query,
4820 struct str_parms *reply,
4821 uint32_t *supported_sample_rates) {
4822
4823 int i;
4824 char value[256];
4825 int ret = -1;
4826 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4827 ret = 0;
4828 value[0] = '\0';
4829 i=0;
4830 int cursor = 0;
4831 while (supported_sample_rates[i]) {
4832 int avail = sizeof(value) - cursor;
4833 ret = snprintf(value + cursor, avail, "%s%d",
4834 cursor > 0 ? "|" : "",
4835 supported_sample_rates[i]);
4836 if (ret < 0 || ret >= avail) {
4837 // if cursor is at the last element of the array
4838 // overwrite with \0 is duplicate work as
4839 // snprintf already put a \0 in place.
4840 // else
4841 // we had space to write the '|' at value[cursor]
4842 // (which will be overwritten) or no space to fill
4843 // the first element (=> cursor == 0)
4844 value[cursor] = '\0';
4845 break;
4846 }
4847 cursor += ret;
4848 ++i;
4849 }
4850 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4851 value);
4852 }
4853 return ret >= 0;
4854}
4855
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004856static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4857{
4858 struct stream_out *out = (struct stream_out *)stream;
4859 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004860 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004861 char value[256];
4862 struct str_parms *reply = str_parms_create();
4863 size_t i, j;
4864 int ret;
4865 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004866
4867 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004868 if (reply) {
4869 str_parms_destroy(reply);
4870 }
4871 if (query) {
4872 str_parms_destroy(query);
4873 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004874 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4875 return NULL;
4876 }
4877
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004878 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004879 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4880 if (ret >= 0) {
4881 value[0] = '\0';
4882 i = 0;
4883 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004884 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4885 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004887 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004888 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004889 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004890 first = false;
4891 break;
4892 }
4893 }
4894 i++;
4895 }
4896 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4897 str = str_parms_to_str(reply);
4898 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004899 voice_extn_out_get_parameters(out, query, reply);
4900 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004901 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004902
Alexy Joseph62142aa2015-11-16 15:10:34 -08004903
4904 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4905 if (ret >= 0) {
4906 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304907 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4908 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004909 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304910 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004911 } else {
4912 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304913 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004914 }
4915 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004916 if (str)
4917 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004918 str = str_parms_to_str(reply);
4919 }
4920
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004921 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4922 if (ret >= 0) {
4923 value[0] = '\0';
4924 i = 0;
4925 first = true;
4926 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004927 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4928 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004929 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004930 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004931 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004932 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004933 first = false;
4934 break;
4935 }
4936 }
4937 i++;
4938 }
4939 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004940 if (str)
4941 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004942 str = str_parms_to_str(reply);
4943 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004944
4945 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4946 if (ret >= 0) {
4947 value[0] = '\0';
4948 i = 0;
4949 first = true;
4950 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004951 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4952 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004953 if (!first) {
4954 strlcat(value, "|", sizeof(value));
4955 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004956 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004957 first = false;
4958 break;
4959 }
4960 }
4961 i++;
4962 }
4963 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4964 if (str)
4965 free(str);
4966 str = str_parms_to_str(reply);
4967 }
4968
Alexy Joseph98988832017-01-13 14:56:59 -08004969 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4970 //only low latency track supports suspend_resume
4971 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004972 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004973 if (str)
4974 free(str);
4975 str = str_parms_to_str(reply);
4976 }
4977
4978
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979 str_parms_destroy(query);
4980 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004981 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004982 return str;
4983}
4984
4985static uint32_t out_get_latency(const struct audio_stream_out *stream)
4986{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004987 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004988 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004989 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004990
Alexy Josephaa54c872014-12-03 02:46:47 -08004991 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304992 lock_output_stream(out);
4993 latency = audio_extn_utils_compress_get_dsp_latency(out);
4994 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004995 } else if ((out->realtime) ||
4996 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004997 // since the buffer won't be filled up faster than realtime,
4998 // return a smaller number
4999 if (out->config.rate)
5000 period_ms = (out->af_period_multiplier * out->config.period_size *
5001 1000) / (out->config.rate);
5002 else
5003 period_ms = 0;
5004 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005005 } else {
5006 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005007 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005008 }
5009
yidongh0515e042017-07-06 15:00:34 +08005010 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005011 latency += audio_extn_a2dp_get_encoder_latency();
5012
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305013 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005014 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005015}
5016
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305017static float AmpToDb(float amplification)
5018{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305019 float db = DSD_VOLUME_MIN_DB;
5020 if (amplification > 0) {
5021 db = 20 * log10(amplification);
5022 if(db < DSD_VOLUME_MIN_DB)
5023 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305024 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305025 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305026}
5027
Arun Mirpuri5d170872019-03-26 13:21:31 -07005028static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5029 float right)
5030{
5031 struct stream_out *out = (struct stream_out *)stream;
5032 long volume = 0;
5033 char mixer_ctl_name[128] = "";
5034 struct audio_device *adev = out->dev;
5035 struct mixer_ctl *ctl = NULL;
5036 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5037 PCM_PLAYBACK);
5038
5039 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5040 "Playback %d Volume", pcm_device_id);
5041 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5042 if (!ctl) {
5043 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5044 __func__, mixer_ctl_name);
5045 return -EINVAL;
5046 }
5047 if (left != right)
5048 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5049 __func__, left, right);
5050 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5051 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5052 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5053 __func__, mixer_ctl_name, volume);
5054 return -EINVAL;
5055 }
5056 return 0;
5057}
5058
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305059static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5060 float right)
5061{
5062 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305063 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305064 char mixer_ctl_name[128];
5065 struct audio_device *adev = out->dev;
5066 struct mixer_ctl *ctl;
5067 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5068 PCM_PLAYBACK);
5069
5070 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5071 "Compress Playback %d Volume", pcm_device_id);
5072 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5073 if (!ctl) {
5074 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5075 __func__, mixer_ctl_name);
5076 return -EINVAL;
5077 }
5078 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5079 __func__, mixer_ctl_name, left, right);
5080 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5081 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5082 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5083
5084 return 0;
5085}
5086
Zhou Song2b8f28f2017-09-11 10:51:38 +08005087static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5088 float right)
5089{
5090 struct stream_out *out = (struct stream_out *)stream;
5091 char mixer_ctl_name[] = "App Type Gain";
5092 struct audio_device *adev = out->dev;
5093 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305094 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005095
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005096 if (!is_valid_volume(left, right)) {
5097 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5098 __func__, left, right);
5099 return -EINVAL;
5100 }
5101
Zhou Song2b8f28f2017-09-11 10:51:38 +08005102 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5103 if (!ctl) {
5104 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5105 __func__, mixer_ctl_name);
5106 return -EINVAL;
5107 }
5108
5109 set_values[0] = 0; //0: Rx Session 1:Tx Session
5110 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305111 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5112 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005113
5114 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5115 return 0;
5116}
5117
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305118static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5119 float right)
5120{
5121 struct stream_out *out = (struct stream_out *)stream;
5122 /* Volume control for pcm playback */
5123 if (left != right) {
5124 return -EINVAL;
5125 } else {
5126 char mixer_ctl_name[128];
5127 struct audio_device *adev = out->dev;
5128 struct mixer_ctl *ctl;
5129 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5130 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5131 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5132 if (!ctl) {
5133 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5134 return -EINVAL;
5135 }
5136
5137 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5138 int ret = mixer_ctl_set_value(ctl, 0, volume);
5139 if (ret < 0) {
5140 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5141 return -EINVAL;
5142 }
5143
5144 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5145
5146 return 0;
5147 }
5148}
5149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005150static int out_set_volume(struct audio_stream_out *stream, float left,
5151 float right)
5152{
Eric Laurenta9024de2013-04-04 09:19:12 -07005153 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005154 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305155 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005156
Arun Mirpuri5d170872019-03-26 13:21:31 -07005157 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005158 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5159 /* only take left channel into account: the API is for stereo anyway */
5160 out->muted = (left == 0.0f);
5161 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005162 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305163 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005164 /*
5165 * Set mute or umute on HDMI passthrough stream.
5166 * Only take left channel into account.
5167 * Mute is 0 and unmute 1
5168 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305169 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305170 } else if (out->format == AUDIO_FORMAT_DSD){
5171 char mixer_ctl_name[128] = "DSD Volume";
5172 struct audio_device *adev = out->dev;
5173 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5174
5175 if (!ctl) {
5176 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5177 __func__, mixer_ctl_name);
5178 return -EINVAL;
5179 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305180 volume[0] = (long)(AmpToDb(left));
5181 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305182 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5183 return 0;
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005184 } else if ((out->devices & AUDIO_DEVICE_OUT_BUS) &&
5185 (audio_extn_auto_hal_get_snd_device_for_car_audio_stream(out) ==
5186 SND_DEVICE_OUT_BUS_MEDIA)) {
5187 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5188 struct listnode *node = NULL;
5189 list_for_each(node, &adev->active_outputs_list) {
5190 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5191 streams_output_ctxt_t,
5192 list);
5193 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5194 out->volume_l = out_ctxt->output->volume_l;
5195 out->volume_r = out_ctxt->output->volume_r;
5196 }
5197 }
5198 if (!out->a2dp_compress_mute) {
5199 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5200 }
5201 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005202 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305203 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005204 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305205 if (!out->a2dp_compress_mute)
5206 ret = out_set_compr_volume(stream, left, right);
5207 out->volume_l = left;
5208 out->volume_r = right;
5209 pthread_mutex_unlock(&out->compr_mute_lock);
5210 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005211 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005212 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005213 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5214 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5215 if (!out->standby) {
5216 audio_extn_utils_send_app_type_gain(out->dev,
5217 out->app_type_cfg.app_type,
5218 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005219 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005220 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005221 out->volume_l = left;
5222 out->volume_r = right;
5223 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005224 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5225 ALOGV("%s: MMAP set volume called", __func__);
5226 if (!out->standby)
5227 ret = out_set_mmap_volume(stream, left, right);
5228 out->volume_l = left;
5229 out->volume_r = right;
5230 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305231 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305232 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5233 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305234 /* Volume control for pcm playback */
5235 if (!out->standby)
5236 ret = out_set_pcm_volume(stream, left, right);
5237 else
5238 out->apply_volume = true;
5239
5240 out->volume_l = left;
5241 out->volume_r = right;
5242 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005243 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5244 ALOGV("%s: bus device set volume called", __func__);
5245 if (!out->standby)
5246 ret = out_set_pcm_volume(stream, left, right);
5247 out->volume_l = left;
5248 out->volume_r = right;
5249 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005250 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005251
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005252 return -ENOSYS;
5253}
5254
Zhou Songc9672822017-08-16 16:01:39 +08005255static void update_frames_written(struct stream_out *out, size_t bytes)
5256{
5257 size_t bpf = 0;
5258
5259 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5260 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5261 bpf = 1;
5262 else if (!is_offload_usecase(out->usecase))
5263 bpf = audio_bytes_per_sample(out->format) *
5264 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005265
5266 pthread_mutex_lock(&out->position_query_lock);
5267 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005268 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005269 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5270 }
5271 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005272}
5273
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005274int split_and_write_audio_haptic_data(struct stream_out *out,
5275 const void *buffer, size_t bytes_to_write)
5276{
5277 struct audio_device *adev = out->dev;
5278
5279 int ret = 0;
5280 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5281 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5282 size_t frame_size = channel_count * bytes_per_sample;
5283 size_t frame_count = bytes_to_write / frame_size;
5284
5285 bool force_haptic_path =
5286 property_get_bool("vendor.audio.test_haptic", false);
5287
5288 // extract Haptics data from Audio buffer
5289 bool alloc_haptic_buffer = false;
5290 int haptic_channel_count = adev->haptics_config.channels;
5291 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5292 size_t audio_frame_size = frame_size - haptic_frame_size;
5293 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5294
5295 if (adev->haptic_buffer == NULL) {
5296 alloc_haptic_buffer = true;
5297 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5298 free(adev->haptic_buffer);
5299 adev->haptic_buffer_size = 0;
5300 alloc_haptic_buffer = true;
5301 }
5302
5303 if (alloc_haptic_buffer) {
5304 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005305 if(adev->haptic_buffer == NULL) {
5306 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5307 return -ENOMEM;
5308 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005309 adev->haptic_buffer_size = total_haptic_buffer_size;
5310 }
5311
5312 size_t src_index = 0, aud_index = 0, hap_index = 0;
5313 uint8_t *audio_buffer = (uint8_t *)buffer;
5314 uint8_t *haptic_buffer = adev->haptic_buffer;
5315
5316 // This is required for testing only. This works for stereo data only.
5317 // One channel is fed to audio stream and other to haptic stream for testing.
5318 if (force_haptic_path)
5319 audio_frame_size = haptic_frame_size = bytes_per_sample;
5320
5321 for (size_t i = 0; i < frame_count; i++) {
5322 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5323 audio_frame_size);
5324 aud_index += audio_frame_size;
5325 src_index += audio_frame_size;
5326
5327 if (adev->haptic_pcm)
5328 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5329 haptic_frame_size);
5330 hap_index += haptic_frame_size;
5331 src_index += haptic_frame_size;
5332
5333 // This is required for testing only.
5334 // Discard haptic channel data.
5335 if (force_haptic_path)
5336 src_index += haptic_frame_size;
5337 }
5338
5339 // write to audio pipeline
5340 ret = pcm_write(out->pcm, (void *)audio_buffer,
5341 frame_count * audio_frame_size);
5342
5343 // write to haptics pipeline
5344 if (adev->haptic_pcm)
5345 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5346 frame_count * haptic_frame_size);
5347
5348 return ret;
5349}
5350
Aalique Grahame22e49102018-12-18 14:23:57 -08005351#ifdef NO_AUDIO_OUT
5352static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5353 const void *buffer __unused, size_t bytes)
5354{
5355 struct stream_out *out = (struct stream_out *)stream;
5356
5357 /* No Output device supported other than BT for playback.
5358 * Sleep for the amount of buffer duration
5359 */
5360 lock_output_stream(out);
5361 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5362 (const struct audio_stream_out *)&out->stream) /
5363 out_get_sample_rate(&out->stream.common));
5364 pthread_mutex_unlock(&out->lock);
5365 return bytes;
5366}
5367#endif
5368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005369static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5370 size_t bytes)
5371{
5372 struct stream_out *out = (struct stream_out *)stream;
5373 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005374 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305375 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005376 const size_t frame_size = audio_stream_out_frame_size(stream);
5377 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305378 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005379
Haynes Mathew George380745d2017-10-04 15:27:45 -07005380 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005381 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305382
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305383 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005384
Dhananjay Kumarac341582017-02-23 23:42:25 +05305385 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305386 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305387 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5388 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005389 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305390 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305391 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305392 ALOGD(" %s: sound card is not active/SSR state", __func__);
5393 ret= -EIO;
5394 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305395 }
5396 }
5397
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305398 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305399 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305400 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305401 goto exit;
5402 }
5403
Haynes Mathew George16081042017-05-31 17:16:49 -07005404 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5405 ret = -EINVAL;
5406 goto exit;
5407 }
5408
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305409 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5410 !out->is_iec61937_info_available) {
5411
5412 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5413 out->is_iec61937_info_available = true;
5414 } else if (audio_extn_passthru_is_enabled()) {
5415 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305416 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305417
5418 if((out->format == AUDIO_FORMAT_DTS) ||
5419 (out->format == AUDIO_FORMAT_DTS_HD)) {
5420 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5421 buffer, bytes);
5422 if (ret) {
5423 if (ret != -ENOSYS) {
5424 out->is_iec61937_info_available = false;
5425 ALOGD("iec61937 transmission info not yet updated retry");
5426 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305427 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305428 /* if stream has started and after that there is
5429 * stream config change (iec transmission config)
5430 * then trigger select_device to update backend configuration.
5431 */
5432 out->stream_config_changed = true;
5433 pthread_mutex_lock(&adev->lock);
5434 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305435 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005436 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305437 ret = -EINVAL;
5438 goto exit;
5439 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305440 pthread_mutex_unlock(&adev->lock);
5441 out->stream_config_changed = false;
5442 out->is_iec61937_info_available = true;
5443 }
5444 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305445
Garmond Leung317cbf12017-09-13 16:20:50 -07005446 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305447 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5448 (out->is_iec61937_info_available == true)) {
5449 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5450 ret = -EINVAL;
5451 goto exit;
5452 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305453 }
5454 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305455
5456 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005457 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005458 if (!(out->devices &
5459 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305460 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305461 ret = -EIO;
5462 goto exit;
5463 }
5464 }
5465 }
5466
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005467 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005468 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005469 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005470 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5471 ret = voice_extn_compress_voip_start_output_stream(out);
5472 else
5473 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005474 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005475 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005476 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005477 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005478 goto exit;
5479 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305480 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005481 if (last_known_cal_step != -1) {
5482 ALOGD("%s: retry previous failed cal level set", __func__);
5483 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305484 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005485 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305486
5487 if ((out->is_iec61937_info_available == true) &&
5488 (audio_extn_passthru_is_passthrough_stream(out))&&
5489 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5490 ret = -EINVAL;
5491 goto exit;
5492 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305493 if (out->set_dual_mono)
5494 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005495 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005496
Ashish Jain81eb2a82015-05-13 10:52:34 +05305497 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005498 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305499 adev->is_channel_status_set = true;
5500 }
5501
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305502 if ((adev->use_old_pspd_mix_ctrl == true) &&
5503 (out->pspd_coeff_sent == false)) {
5504 /*
5505 * Need to resend pspd coefficients after stream started for
5506 * older kernel version as it does not save the coefficients
5507 * and also stream has to be started for coeff to apply.
5508 */
5509 usecase = get_usecase_from_list(adev, out->usecase);
5510 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305511 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305512 out->pspd_coeff_sent = true;
5513 }
5514 }
5515
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005516 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005517 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005518 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005519 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005520 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5521 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305522 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5523 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangebfa0502019-07-18 17:24:21 +08005524 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305525 out->send_next_track_params = false;
5526 out->is_compr_metadata_avail = false;
5527 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005528 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305529 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305530 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005531
Ashish Jain83a6cc22016-06-28 14:34:17 +05305532 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305533 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305534 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305535 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005536 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305537 return -EINVAL;
5538 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305539 audio_format_t dst_format = out->hal_op_format;
5540 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305541
Dieter Luecking5d57def2018-09-07 14:23:37 +02005542 /* prevent division-by-zero */
5543 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5544 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5545 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5546 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305547 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005548 ATRACE_END();
5549 return -EINVAL;
5550 }
5551
Ashish Jainf1eaa582016-05-23 20:54:24 +05305552 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5553 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5554
Ashish Jain83a6cc22016-06-28 14:34:17 +05305555 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305556 dst_format,
5557 buffer,
5558 src_format,
5559 frames);
5560
Ashish Jain83a6cc22016-06-28 14:34:17 +05305561 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305562 bytes_to_write);
5563
5564 /*Convert written bytes in audio flinger format*/
5565 if (ret > 0)
5566 ret = ((ret * format_to_bitwidth_table[out->format]) /
5567 format_to_bitwidth_table[dst_format]);
5568 }
5569 } else
5570 ret = compress_write(out->compr, buffer, bytes);
5571
Zhou Songc9672822017-08-16 16:01:39 +08005572 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5573 update_frames_written(out, bytes);
5574
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305575 if (ret < 0)
5576 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005577 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305578 /*msg to cb thread only if non blocking write is enabled*/
5579 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305580 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005581 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305582 } else if (-ENETRESET == ret) {
5583 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305584 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305585 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305586 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005587 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305588 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005589 }
Ashish Jain5106d362016-05-11 19:23:33 +05305590
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305591 /* Call compr start only when non-zero bytes of data is there to be rendered */
5592 if (!out->playback_started && ret > 0) {
5593 int status = compress_start(out->compr);
5594 if (status < 0) {
5595 ret = status;
5596 ALOGE("%s: compr start failed with err %d", __func__, errno);
5597 goto exit;
5598 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005599 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005600 out->playback_started = 1;
5601 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005602
5603 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5604 popcount(out->channel_mask),
5605 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005606 }
5607 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005608 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005609 return ret;
5610 } else {
5611 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005612 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005613 if (out->muted)
5614 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005615 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5616 __func__, frames, frame_size, bytes_to_write);
5617
Aalique Grahame22e49102018-12-18 14:23:57 -08005618 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005619 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5620 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5621 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005622 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5623 int16_t *src = (int16_t *)buffer;
5624 int16_t *dst = (int16_t *)buffer;
5625
5626 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5627 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005628 "out_write called for %s use case with wrong properties",
5629 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005630
5631 /*
5632 * FIXME: this can be removed once audio flinger mixer supports
5633 * mono output
5634 */
5635
5636 /*
5637 * Code below goes over each frame in the buffer and adds both
5638 * L and R samples and then divides by 2 to convert to mono
5639 */
5640 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5641 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5642 }
5643 bytes_to_write /= 2;
5644 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005645
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305646 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005647
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005648 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005649
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005650 if (out->config.rate)
5651 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5652 out->config.rate;
5653
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005654 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005655 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5656
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005657 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005658 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005659 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305660 out->convert_buffer != NULL) {
5661
5662 memcpy_by_audio_format(out->convert_buffer,
5663 out->hal_op_format,
5664 buffer,
5665 out->hal_ip_format,
5666 out->config.period_size * out->config.channels);
5667
5668 ret = pcm_write(out->pcm, out->convert_buffer,
5669 (out->config.period_size *
5670 out->config.channels *
5671 format_to_bitwidth_table[out->hal_op_format]));
5672 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305673 /*
5674 * To avoid underrun in DSP when the application is not pumping
5675 * data at required rate, check for the no. of bytes and ignore
5676 * pcm_write if it is less than actual buffer size.
5677 * It is a work around to a change in compress VOIP driver.
5678 */
5679 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5680 bytes < (out->config.period_size * out->config.channels *
5681 audio_bytes_per_sample(out->format))) {
5682 size_t voip_buf_size =
5683 out->config.period_size * out->config.channels *
5684 audio_bytes_per_sample(out->format);
5685 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5686 __func__, bytes, voip_buf_size);
5687 usleep(((uint64_t)voip_buf_size - bytes) *
5688 1000000 / audio_stream_out_frame_size(stream) /
5689 out_get_sample_rate(&out->stream.common));
5690 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005691 } else {
5692 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5693 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5694 else
5695 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5696 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305697 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005698
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005699 release_out_focus(out);
5700
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305701 if (ret < 0)
5702 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005703 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305704 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005705 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005706 }
5707
5708exit:
Zhou Songc9672822017-08-16 16:01:39 +08005709 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305710 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305711 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305712 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005713 pthread_mutex_unlock(&out->lock);
5714
5715 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005716 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005717 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305718 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305719 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305720 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305721 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305722 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305723 out->standby = true;
5724 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305725 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005726 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5727 /* prevent division-by-zero */
5728 uint32_t stream_size = audio_stream_out_frame_size(stream);
5729 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005730
Dieter Luecking5d57def2018-09-07 14:23:37 +02005731 if ((stream_size == 0) || (srate == 0)) {
5732 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5733 ATRACE_END();
5734 return -EINVAL;
5735 }
5736 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5737 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005738 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305739 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005740 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005741 return ret;
5742 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005743 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005744 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005745 return bytes;
5746}
5747
5748static int out_get_render_position(const struct audio_stream_out *stream,
5749 uint32_t *dsp_frames)
5750{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005751 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005752
5753 if (dsp_frames == NULL)
5754 return -EINVAL;
5755
5756 *dsp_frames = 0;
5757 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005758 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305759
5760 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5761 * this operation and adev_close_output_stream(where out gets reset).
5762 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305763 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005764 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305765 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005766 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305767 return 0;
5768 }
5769
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005770 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305771 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305772 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005773 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305774 if (ret < 0)
5775 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005776 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305777 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005778 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305779 if (-ENETRESET == ret) {
5780 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305781 out->card_status = CARD_STATUS_OFFLINE;
5782 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305783 } else if(ret < 0) {
5784 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305785 ret = -EINVAL;
5786 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305787 /*
5788 * Handle corner case where compress session is closed during SSR
5789 * and timestamp is queried
5790 */
5791 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305792 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305793 } else if (out->prev_card_status_offline) {
5794 ALOGE("ERROR: previously sound card was offline,return error");
5795 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305796 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305797 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005798 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305799 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305800 pthread_mutex_unlock(&out->lock);
5801 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005802 } else if (audio_is_linear_pcm(out->format)) {
5803 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005804 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005805 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005806 } else
5807 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005808}
5809
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005810static int out_add_audio_effect(const struct audio_stream *stream __unused,
5811 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005812{
5813 return 0;
5814}
5815
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005816static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5817 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005818{
5819 return 0;
5820}
5821
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005822static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5823 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005824{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305825 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005826}
5827
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005828static int out_get_presentation_position(const struct audio_stream_out *stream,
5829 uint64_t *frames, struct timespec *timestamp)
5830{
5831 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305832 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005833 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005834
Ashish Jain5106d362016-05-11 19:23:33 +05305835 /* below piece of code is not guarded against any lock because audioFliner serializes
5836 * this operation and adev_close_output_stream( where out gets reset).
5837 */
5838 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305839 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005840 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305841 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5842 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5843 return 0;
5844 }
5845
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005846 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005847
Ashish Jain5106d362016-05-11 19:23:33 +05305848 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5849 ret = compress_get_tstamp(out->compr, &dsp_frames,
5850 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005851 // Adjustment accounts for A2dp encoder latency with offload usecases
5852 // Note: Encoder latency is returned in ms.
5853 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5854 unsigned long offset =
5855 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5856 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5857 }
Ashish Jain5106d362016-05-11 19:23:33 +05305858 ALOGVV("%s rendered frames %ld sample_rate %d",
5859 __func__, dsp_frames, out->sample_rate);
5860 *frames = dsp_frames;
5861 if (ret < 0)
5862 ret = -errno;
5863 if (-ENETRESET == ret) {
5864 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305865 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305866 ret = -EINVAL;
5867 } else
5868 ret = 0;
5869 /* this is the best we can do */
5870 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005871 } else {
5872 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005873 unsigned int avail;
5874 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5875 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5876 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5877 // This adjustment accounts for buffering after app processor.
5878 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005879 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005880 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005881
Weiyin Jiangd4633762018-03-16 12:05:03 +08005882 // Adjustment accounts for A2dp encoder latency with non offload usecases
5883 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5884 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5885 signed_frames -=
5886 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5887 }
5888
5889 // It would be unusual for this value to be negative, but check just in case ...
5890 if (signed_frames >= 0) {
5891 *frames = signed_frames;
5892 ret = 0;
5893 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005894 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305895 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305896 *frames = out->written;
5897 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305898 if (is_offload_usecase(out->usecase))
5899 ret = -EINVAL;
5900 else
5901 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005902 }
5903 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005904 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005905 return ret;
5906}
5907
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005908static int out_set_callback(struct audio_stream_out *stream,
5909 stream_callback_t callback, void *cookie)
5910{
5911 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005912 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005913
5914 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005915 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005916 out->client_callback = callback;
5917 out->client_cookie = cookie;
5918 if (out->adsp_hdlr_stream_handle) {
5919 ret = audio_extn_adsp_hdlr_stream_set_callback(
5920 out->adsp_hdlr_stream_handle,
5921 callback,
5922 cookie);
5923 if (ret)
5924 ALOGW("%s:adsp hdlr callback registration failed %d",
5925 __func__, ret);
5926 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005927 pthread_mutex_unlock(&out->lock);
5928 return 0;
5929}
5930
5931static int out_pause(struct audio_stream_out* stream)
5932{
5933 struct stream_out *out = (struct stream_out *)stream;
5934 int status = -ENOSYS;
5935 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005936 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005937 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005938 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005939 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305940 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305941 status = compress_pause(out->compr);
5942
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005943 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005944
Mingming Yin21854652016-04-13 11:54:02 -07005945 if (audio_extn_passthru_is_active()) {
5946 ALOGV("offload use case, pause passthru");
5947 audio_extn_passthru_on_pause(out);
5948 }
5949
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305950 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005951 audio_extn_dts_notify_playback_state(out->usecase, 0,
5952 out->sample_rate, popcount(out->channel_mask),
5953 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005954 }
5955 pthread_mutex_unlock(&out->lock);
5956 }
5957 return status;
5958}
5959
5960static int out_resume(struct audio_stream_out* stream)
5961{
5962 struct stream_out *out = (struct stream_out *)stream;
5963 int status = -ENOSYS;
5964 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005965 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005966 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005967 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005968 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005969 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305970 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305971 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005972 }
5973 if (!status) {
5974 out->offload_state = OFFLOAD_STATE_PLAYING;
5975 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305976 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005977 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5978 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005979 }
5980 pthread_mutex_unlock(&out->lock);
5981 }
5982 return status;
5983}
5984
5985static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5986{
5987 struct stream_out *out = (struct stream_out *)stream;
5988 int status = -ENOSYS;
5989 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005990 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005991 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005992 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5993 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5994 else
5995 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5996 pthread_mutex_unlock(&out->lock);
5997 }
5998 return status;
5999}
6000
6001static int out_flush(struct audio_stream_out* stream)
6002{
6003 struct stream_out *out = (struct stream_out *)stream;
6004 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006005 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006006 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006007 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006008 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6009 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006010 } else {
6011 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6012 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006013 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006014 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006015 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006016 return 0;
6017 }
6018 return -ENOSYS;
6019}
6020
Haynes Mathew George16081042017-05-31 17:16:49 -07006021static int out_stop(const struct audio_stream_out* stream)
6022{
6023 struct stream_out *out = (struct stream_out *)stream;
6024 struct audio_device *adev = out->dev;
6025 int ret = -ENOSYS;
6026
6027 ALOGV("%s", __func__);
6028 pthread_mutex_lock(&adev->lock);
6029 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6030 out->playback_started && out->pcm != NULL) {
6031 pcm_stop(out->pcm);
6032 ret = stop_output_stream(out);
6033 out->playback_started = false;
6034 }
6035 pthread_mutex_unlock(&adev->lock);
6036 return ret;
6037}
6038
6039static int out_start(const struct audio_stream_out* stream)
6040{
6041 struct stream_out *out = (struct stream_out *)stream;
6042 struct audio_device *adev = out->dev;
6043 int ret = -ENOSYS;
6044
6045 ALOGV("%s", __func__);
6046 pthread_mutex_lock(&adev->lock);
6047 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6048 !out->playback_started && out->pcm != NULL) {
6049 ret = start_output_stream(out);
6050 if (ret == 0) {
6051 out->playback_started = true;
6052 }
6053 }
6054 pthread_mutex_unlock(&adev->lock);
6055 return ret;
6056}
6057
6058/*
6059 * Modify config->period_count based on min_size_frames
6060 */
6061static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6062{
6063 int periodCountRequested = (min_size_frames + config->period_size - 1)
6064 / config->period_size;
6065 int periodCount = MMAP_PERIOD_COUNT_MIN;
6066
6067 ALOGV("%s original config.period_size = %d config.period_count = %d",
6068 __func__, config->period_size, config->period_count);
6069
6070 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6071 periodCount *= 2;
6072 }
6073 config->period_count = periodCount;
6074
6075 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6076}
6077
Phil Burkfe17efd2019-03-25 10:23:35 -07006078// Read offset for the positional timestamp from a persistent vendor property.
6079// This is to workaround apparent inaccuracies in the timing information that
6080// is used by the AAudio timing model. The inaccuracies can cause glitches.
6081static int64_t get_mmap_out_time_offset() {
6082 const int32_t kDefaultOffsetMicros = 0;
6083 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006084 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006085 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6086 return mmap_time_offset_micros * (int64_t)1000;
6087}
6088
Haynes Mathew George16081042017-05-31 17:16:49 -07006089static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6090 int32_t min_size_frames,
6091 struct audio_mmap_buffer_info *info)
6092{
6093 struct stream_out *out = (struct stream_out *)stream;
6094 struct audio_device *adev = out->dev;
6095 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006096 unsigned int offset1 = 0;
6097 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006098 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006099 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006100 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006101
Arun Mirpuri5d170872019-03-26 13:21:31 -07006102 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306103 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006104 pthread_mutex_lock(&adev->lock);
6105
Sharad Sanglec6f32552018-05-04 16:15:38 +05306106 if (CARD_STATUS_OFFLINE == out->card_status ||
6107 CARD_STATUS_OFFLINE == adev->card_status) {
6108 ALOGW("out->card_status or adev->card_status offline, try again");
6109 ret = -EIO;
6110 goto exit;
6111 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006112 if (info == NULL || min_size_frames == 0) {
6113 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6114 ret = -EINVAL;
6115 goto exit;
6116 }
6117 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6118 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6119 ret = -ENOSYS;
6120 goto exit;
6121 }
6122 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6123 if (out->pcm_device_id < 0) {
6124 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6125 __func__, out->pcm_device_id, out->usecase);
6126 ret = -EINVAL;
6127 goto exit;
6128 }
6129
6130 adjust_mmap_period_count(&out->config, min_size_frames);
6131
Arun Mirpuri5d170872019-03-26 13:21:31 -07006132 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006133 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6134 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6135 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306136 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306137 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6138 out->card_status = CARD_STATUS_OFFLINE;
6139 adev->card_status = CARD_STATUS_OFFLINE;
6140 ret = -EIO;
6141 goto exit;
6142 }
6143
Haynes Mathew George16081042017-05-31 17:16:49 -07006144 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6145 step = "open";
6146 ret = -ENODEV;
6147 goto exit;
6148 }
6149 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6150 if (ret < 0) {
6151 step = "begin";
6152 goto exit;
6153 }
6154 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006155 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006156 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006157 ret = platform_get_mmap_data_fd(adev->platform,
6158 out->pcm_device_id, 0 /*playback*/,
6159 &info->shared_memory_fd,
6160 &mmap_size);
6161 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006162 // Fall back to non exclusive mode
6163 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6164 } else {
6165 if (mmap_size < buffer_size) {
6166 step = "mmap";
6167 goto exit;
6168 }
6169 // FIXME: indicate exclusive mode support by returning a negative buffer size
6170 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006171 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006172 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006173 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006174
6175 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6176 if (ret < 0) {
6177 step = "commit";
6178 goto exit;
6179 }
6180
Phil Burkfe17efd2019-03-25 10:23:35 -07006181 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6182
Haynes Mathew George16081042017-05-31 17:16:49 -07006183 out->standby = false;
6184 ret = 0;
6185
Arun Mirpuri5d170872019-03-26 13:21:31 -07006186 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006187 __func__, info->shared_memory_address, info->buffer_size_frames);
6188
6189exit:
6190 if (ret != 0) {
6191 if (out->pcm == NULL) {
6192 ALOGE("%s: %s - %d", __func__, step, ret);
6193 } else {
6194 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6195 pcm_close(out->pcm);
6196 out->pcm = NULL;
6197 }
6198 }
6199 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306200 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006201 return ret;
6202}
6203
6204static int out_get_mmap_position(const struct audio_stream_out *stream,
6205 struct audio_mmap_position *position)
6206{
6207 struct stream_out *out = (struct stream_out *)stream;
6208 ALOGVV("%s", __func__);
6209 if (position == NULL) {
6210 return -EINVAL;
6211 }
6212 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006213 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006214 return -ENOSYS;
6215 }
6216 if (out->pcm == NULL) {
6217 return -ENOSYS;
6218 }
6219
6220 struct timespec ts = { 0, 0 };
6221 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6222 if (ret < 0) {
6223 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6224 return ret;
6225 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006226 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6227 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006228 return 0;
6229}
6230
6231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006232/** audio_stream_in implementation **/
6233static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6234{
6235 struct stream_in *in = (struct stream_in *)stream;
6236
6237 return in->config.rate;
6238}
6239
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006240static int in_set_sample_rate(struct audio_stream *stream __unused,
6241 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006242{
6243 return -ENOSYS;
6244}
6245
6246static size_t in_get_buffer_size(const struct audio_stream *stream)
6247{
6248 struct stream_in *in = (struct stream_in *)stream;
6249
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006250 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6251 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006252 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6253 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306254 else if(audio_extn_cin_attached_usecase(in->usecase))
6255 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006256
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006257 return in->config.period_size * in->af_period_multiplier *
6258 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006259}
6260
6261static uint32_t in_get_channels(const struct audio_stream *stream)
6262{
6263 struct stream_in *in = (struct stream_in *)stream;
6264
6265 return in->channel_mask;
6266}
6267
6268static audio_format_t in_get_format(const struct audio_stream *stream)
6269{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006270 struct stream_in *in = (struct stream_in *)stream;
6271
6272 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006273}
6274
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006275static int in_set_format(struct audio_stream *stream __unused,
6276 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006277{
6278 return -ENOSYS;
6279}
6280
6281static int in_standby(struct audio_stream *stream)
6282{
6283 struct stream_in *in = (struct stream_in *)stream;
6284 struct audio_device *adev = in->dev;
6285 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306286 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6287 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006288 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306289
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006290 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006291 if (!in->standby && in->is_st_session) {
6292 ALOGD("%s: sound trigger pcm stop lab", __func__);
6293 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006294 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006295 in->standby = 1;
6296 }
6297
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006298 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006299 if (adev->adm_deregister_stream)
6300 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6301
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006302 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006303 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006304 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006305 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006306 voice_extn_compress_voip_close_input_stream(stream);
6307 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006308 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6309 do_stop = in->capture_started;
6310 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006311 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306312 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05306313 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006314 }
6315
Arun Mirpuri5d170872019-03-26 13:21:31 -07006316 if (in->pcm) {
6317 ATRACE_BEGIN("pcm_in_close");
6318 pcm_close(in->pcm);
6319 ATRACE_END();
6320 in->pcm = NULL;
6321 }
6322
Carter Hsu2e429db2019-05-14 18:50:52 +08006323 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Aalique Grahame22e49102018-12-18 14:23:57 -08006324 adev->enable_voicerx = false;
Carter Hsu2e429db2019-05-14 18:50:52 +08006325
6326 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006327 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006328
6329 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6330 adev->num_va_sessions--;
6331
Eric Laurent150dbfe2013-02-27 14:31:02 -08006332 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006333 }
6334 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006335 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006336 return status;
6337}
6338
Aalique Grahame22e49102018-12-18 14:23:57 -08006339static int in_dump(const struct audio_stream *stream,
6340 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006341{
Aalique Grahame22e49102018-12-18 14:23:57 -08006342 struct stream_in *in = (struct stream_in *)stream;
6343
6344 // We try to get the lock for consistency,
6345 // but it isn't necessary for these variables.
6346 // If we're not in standby, we may be blocked on a read.
6347 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6348 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6349 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6350 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6351
6352 if (locked) {
6353 pthread_mutex_unlock(&in->lock);
6354 }
6355
6356 // dump error info
6357 (void)error_log_dump(
6358 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6359
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006360 return 0;
6361}
6362
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306363static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6364{
6365 if (!stream || !parms)
6366 return;
6367
6368 struct stream_in *in = (struct stream_in *)stream;
6369 struct audio_device *adev = in->dev;
6370
6371 card_status_t status;
6372 int card;
6373 if (parse_snd_card_status(parms, &card, &status) < 0)
6374 return;
6375
6376 pthread_mutex_lock(&adev->lock);
6377 bool valid_cb = (card == adev->snd_card);
6378 pthread_mutex_unlock(&adev->lock);
6379
6380 if (!valid_cb)
6381 return;
6382
6383 lock_input_stream(in);
6384 if (in->card_status != status)
6385 in->card_status = status;
6386 pthread_mutex_unlock(&in->lock);
6387
6388 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6389 use_case_table[in->usecase],
6390 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6391
6392 // a better solution would be to report error back to AF and let
6393 // it put the stream to standby
6394 if (status == CARD_STATUS_OFFLINE)
6395 in_standby(&in->stream.common);
6396
6397 return;
6398}
6399
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006400static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6401{
6402 struct stream_in *in = (struct stream_in *)stream;
6403 struct audio_device *adev = in->dev;
6404 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006405 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006406 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006407
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306408 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006409 parms = str_parms_create_str(kvpairs);
6410
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306411 if (!parms)
6412 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006413 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006414 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006415
6416 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6417 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006418 val = atoi(value);
6419 /* no audio source uses val == 0 */
6420 if ((in->source != val) && (val != 0)) {
6421 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006422 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6423 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6424 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006425 (in->config.rate == 8000 || in->config.rate == 16000 ||
6426 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006427 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006428 err = voice_extn_compress_voip_open_input_stream(in);
6429 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006430 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006431 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006432 }
6433 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006434 }
6435 }
6436
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006437 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6438 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006439 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006440 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6441
6442 // Workaround: If routing to an non existing usb device, fail gracefully
6443 // The routing request will otherwise block during 10 second
6444 int card;
6445 if (audio_is_usb_in_device(val) &&
6446 (card = get_alive_usb_card(parms)) >= 0) {
6447
6448 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6449 ret = -ENOSYS;
6450 } else {
6451
6452 in->device = val;
6453 /* If recording is in progress, change the tx device to new device */
6454 if (!in->standby && !in->is_st_session) {
6455 ALOGV("update input routing change");
6456 // inform adm before actual routing to prevent glitches.
6457 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006458 adev->adm_on_routing_change(adev->adm_data,
6459 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006460 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006461 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6462 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006463 }
6464 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006465 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006466 }
6467 }
6468
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306469 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6470 if (err >= 0) {
6471 strlcpy(in->profile, value, sizeof(in->profile));
6472 ALOGV("updating stream profile with value '%s'", in->profile);
6473 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6474 &adev->streams_input_cfg_list,
6475 in->device, in->flags, in->format,
6476 in->sample_rate, in->bit_width,
6477 in->profile, &in->app_type_cfg);
6478 }
6479
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006480 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006481 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006482
6483 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306484error:
Eric Laurent994a6932013-07-17 11:51:42 -07006485 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006486 return ret;
6487}
6488
6489static char* in_get_parameters(const struct audio_stream *stream,
6490 const char *keys)
6491{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006492 struct stream_in *in = (struct stream_in *)stream;
6493 struct str_parms *query = str_parms_create_str(keys);
6494 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006495 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006496
6497 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006498 if (reply) {
6499 str_parms_destroy(reply);
6500 }
6501 if (query) {
6502 str_parms_destroy(query);
6503 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006504 ALOGE("in_get_parameters: failed to create query or reply");
6505 return NULL;
6506 }
6507
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006508 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006509
6510 voice_extn_in_get_parameters(in, query, reply);
6511
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006512 stream_get_parameter_channels(query, reply,
6513 &in->supported_channel_masks[0]);
6514 stream_get_parameter_formats(query, reply,
6515 &in->supported_formats[0]);
6516 stream_get_parameter_rates(query, reply,
6517 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006518 str = str_parms_to_str(reply);
6519 str_parms_destroy(query);
6520 str_parms_destroy(reply);
6521
6522 ALOGV("%s: exit: returns - %s", __func__, str);
6523 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006524}
6525
Aalique Grahame22e49102018-12-18 14:23:57 -08006526static int in_set_gain(struct audio_stream_in *stream,
6527 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006528{
Aalique Grahame22e49102018-12-18 14:23:57 -08006529 struct stream_in *in = (struct stream_in *)stream;
6530 char mixer_ctl_name[128];
6531 struct mixer_ctl *ctl;
6532 int ctl_value;
6533
6534 ALOGV("%s: gain %f", __func__, gain);
6535
6536 if (stream == NULL)
6537 return -EINVAL;
6538
6539 /* in_set_gain() only used to silence MMAP capture for now */
6540 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6541 return -ENOSYS;
6542
6543 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6544
6545 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6546 if (!ctl) {
6547 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6548 __func__, mixer_ctl_name);
6549 return -ENOSYS;
6550 }
6551
6552 if (gain < RECORD_GAIN_MIN)
6553 gain = RECORD_GAIN_MIN;
6554 else if (gain > RECORD_GAIN_MAX)
6555 gain = RECORD_GAIN_MAX;
6556 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6557
6558 mixer_ctl_set_value(ctl, 0, ctl_value);
6559
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006560 return 0;
6561}
6562
6563static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6564 size_t bytes)
6565{
6566 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306567
6568 if (in == NULL) {
6569 ALOGE("%s: stream_in ptr is NULL", __func__);
6570 return -EINVAL;
6571 }
6572
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006573 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306574 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306575 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006576
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006577 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306578
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006579 if (in->is_st_session) {
6580 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6581 /* Read from sound trigger HAL */
6582 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006583 if (in->standby) {
6584 adev->num_va_sessions++;
6585 in->standby = 0;
6586 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006587 pthread_mutex_unlock(&in->lock);
6588 return bytes;
6589 }
6590
Haynes Mathew George16081042017-05-31 17:16:49 -07006591 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6592 ret = -ENOSYS;
6593 goto exit;
6594 }
6595
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006596 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6597 !in->standby && adev->adm_routing_changed) {
6598 ret = -ENOSYS;
6599 goto exit;
6600 }
6601
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006602 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006603 pthread_mutex_lock(&adev->lock);
6604 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6605 ret = voice_extn_compress_voip_start_input_stream(in);
6606 else
6607 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006608 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6609 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006610 pthread_mutex_unlock(&adev->lock);
6611 if (ret != 0) {
6612 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006613 }
6614 in->standby = 0;
6615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006616
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306617 /* Avoid read if capture_stopped is set */
6618 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6619 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6620 ret = -EINVAL;
6621 goto exit;
6622 }
6623
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006624 // what's the duration requested by the client?
6625 long ns = 0;
6626
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306627 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006628 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6629 in->config.rate;
6630
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006631 ret = request_in_focus(in, ns);
6632 if (ret != 0)
6633 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006634 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006635
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306636 if (audio_extn_cin_attached_usecase(in->usecase)) {
6637 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6638 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306639 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006640 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306641 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006642 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006643 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006644 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006645 } else if (audio_extn_ffv_get_stream() == in) {
6646 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306647 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006648 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306649 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6650 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6651 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6652 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306653 ret = -EINVAL;
6654 goto exit;
6655 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306656 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306657 ret = -errno;
6658 }
6659 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306660 /* bytes read is always set to bytes for non compress usecases */
6661 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006662 }
6663
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006664 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006665
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006666 /*
Quinn Malef6050362019-01-30 15:55:40 -08006667 * Instead of writing zeroes here, we could trust the hardware to always
6668 * provide zeroes when muted. This is also muted with voice recognition
6669 * usecases so that other clients do not have access to voice recognition
6670 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006671 */
Quinn Malef6050362019-01-30 15:55:40 -08006672 if ((ret == 0 && voice_get_mic_mute(adev) &&
6673 !voice_is_in_call_rec_stream(in) &&
6674 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6675 (adev->num_va_sessions &&
6676 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6677 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6678 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006679 memset(buffer, 0, bytes);
6680
6681exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306682 frame_size = audio_stream_in_frame_size(stream);
6683 if (frame_size > 0)
6684 in->frames_read += bytes_read/frame_size;
6685
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006686 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306687 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006688 pthread_mutex_unlock(&in->lock);
6689
6690 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306691 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306692 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306693 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306694 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306695 in->standby = true;
6696 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306697 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6698 bytes_read = bytes;
6699 memset(buffer, 0, bytes);
6700 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006701 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006702 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6703 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006704 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306705 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306706 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006707 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306708 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006709}
6710
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006711static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006712{
6713 return 0;
6714}
6715
Aalique Grahame22e49102018-12-18 14:23:57 -08006716static int in_get_capture_position(const struct audio_stream_in *stream,
6717 int64_t *frames, int64_t *time)
6718{
6719 if (stream == NULL || frames == NULL || time == NULL) {
6720 return -EINVAL;
6721 }
6722 struct stream_in *in = (struct stream_in *)stream;
6723 int ret = -ENOSYS;
6724
6725 lock_input_stream(in);
6726 // note: ST sessions do not close the alsa pcm driver synchronously
6727 // on standby. Therefore, we may return an error even though the
6728 // pcm stream is still opened.
6729 if (in->standby) {
6730 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6731 "%s stream in standby but pcm not NULL for non ST session", __func__);
6732 goto exit;
6733 }
6734 if (in->pcm) {
6735 struct timespec timestamp;
6736 unsigned int avail;
6737 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6738 *frames = in->frames_read + avail;
6739 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6740 ret = 0;
6741 }
6742 }
6743exit:
6744 pthread_mutex_unlock(&in->lock);
6745 return ret;
6746}
6747
Carter Hsu2e429db2019-05-14 18:50:52 +08006748static int in_update_effect_list(bool add, effect_handle_t effect,
6749 struct listnode *head)
6750{
6751 struct listnode *node;
6752 struct in_effect_list *elist = NULL;
6753 struct in_effect_list *target = NULL;
6754 int ret = 0;
6755
6756 if (!head)
6757 return ret;
6758
6759 list_for_each(node, head) {
6760 elist = node_to_item(node, struct in_effect_list, list);
6761 if (elist->handle == effect) {
6762 target = elist;
6763 break;
6764 }
6765 }
6766
6767 if (add) {
6768 if (target) {
6769 ALOGD("effect %p already exist", effect);
6770 return ret;
6771 }
6772
6773 target = (struct in_effect_list *)
6774 calloc(1, sizeof(struct in_effect_list));
6775
6776 if (!target) {
6777 ALOGE("%s:fail to allocate memory", __func__);
6778 return -ENOMEM;
6779 }
6780
6781 target->handle = effect;
6782 list_add_tail(head, &target->list);
6783 } else {
6784 if (target) {
6785 list_remove(&target->list);
6786 free(target);
6787 }
6788 }
6789
6790 return ret;
6791}
6792
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006793static int add_remove_audio_effect(const struct audio_stream *stream,
6794 effect_handle_t effect,
6795 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006796{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006797 struct stream_in *in = (struct stream_in *)stream;
6798 int status = 0;
6799 effect_descriptor_t desc;
6800
6801 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006802 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6803
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006804 if (status != 0)
6805 return status;
6806
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006807 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006808 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006809 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08006810 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
6811 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006812 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08006813
6814 in_update_effect_list(enable, effect, &in->aec_list);
6815 enable = !list_empty(&in->aec_list);
6816 if (enable == in->enable_aec)
6817 goto exit;
6818
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006819 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006820 ALOGD("AEC enable %d", enable);
6821
Aalique Grahame22e49102018-12-18 14:23:57 -08006822 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6823 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6824 in->dev->enable_voicerx = enable;
6825 struct audio_usecase *usecase;
6826 struct listnode *node;
6827 list_for_each(node, &in->dev->usecase_list) {
6828 usecase = node_to_item(node, struct audio_usecase, list);
6829 if (usecase->type == PCM_PLAYBACK)
6830 select_devices(in->dev, usecase->id);
6831 }
6832 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006833 if (!in->standby) {
6834 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6835 select_devices(in->dev, in->usecase);
6836 }
6837
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006838 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006839 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
6840
6841 in_update_effect_list(enable, effect, &in->ns_list);
6842 enable = !list_empty(&in->ns_list);
6843 if (enable == in->enable_ns)
6844 goto exit;
6845
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006846 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006847 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006848 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006849 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6850 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006851 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6852 select_devices(in->dev, in->usecase);
6853 } else
6854 select_devices(in->dev, in->usecase);
6855 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006856 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006857exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006858 pthread_mutex_unlock(&in->dev->lock);
6859 pthread_mutex_unlock(&in->lock);
6860
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006861 return 0;
6862}
6863
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006864static int in_add_audio_effect(const struct audio_stream *stream,
6865 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006866{
Eric Laurent994a6932013-07-17 11:51:42 -07006867 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006868 return add_remove_audio_effect(stream, effect, true);
6869}
6870
6871static int in_remove_audio_effect(const struct audio_stream *stream,
6872 effect_handle_t effect)
6873{
Eric Laurent994a6932013-07-17 11:51:42 -07006874 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006875 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006876}
6877
Derek Chenf939fb72018-11-13 13:34:41 -08006878streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6879 audio_io_handle_t input)
6880{
6881 struct listnode *node;
6882
6883 list_for_each(node, &dev->active_inputs_list) {
6884 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6885 streams_input_ctxt_t,
6886 list);
6887 if (in_ctxt->input->capture_handle == input) {
6888 return in_ctxt;
6889 }
6890 }
6891 return NULL;
6892}
6893
6894streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6895 audio_io_handle_t output)
6896{
6897 struct listnode *node;
6898
6899 list_for_each(node, &dev->active_outputs_list) {
6900 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6901 streams_output_ctxt_t,
6902 list);
6903 if (out_ctxt->output->handle == output) {
6904 return out_ctxt;
6905 }
6906 }
6907 return NULL;
6908}
6909
Haynes Mathew George16081042017-05-31 17:16:49 -07006910static int in_stop(const struct audio_stream_in* stream)
6911{
6912 struct stream_in *in = (struct stream_in *)stream;
6913 struct audio_device *adev = in->dev;
6914
6915 int ret = -ENOSYS;
6916 ALOGV("%s", __func__);
6917 pthread_mutex_lock(&adev->lock);
6918 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6919 in->capture_started && in->pcm != NULL) {
6920 pcm_stop(in->pcm);
6921 ret = stop_input_stream(in);
6922 in->capture_started = false;
6923 }
6924 pthread_mutex_unlock(&adev->lock);
6925 return ret;
6926}
6927
6928static int in_start(const struct audio_stream_in* stream)
6929{
6930 struct stream_in *in = (struct stream_in *)stream;
6931 struct audio_device *adev = in->dev;
6932 int ret = -ENOSYS;
6933
6934 ALOGV("%s in %p", __func__, in);
6935 pthread_mutex_lock(&adev->lock);
6936 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6937 !in->capture_started && in->pcm != NULL) {
6938 if (!in->capture_started) {
6939 ret = start_input_stream(in);
6940 if (ret == 0) {
6941 in->capture_started = true;
6942 }
6943 }
6944 }
6945 pthread_mutex_unlock(&adev->lock);
6946 return ret;
6947}
6948
Phil Burke0a86d12019-02-16 22:28:11 -08006949// Read offset for the positional timestamp from a persistent vendor property.
6950// This is to workaround apparent inaccuracies in the timing information that
6951// is used by the AAudio timing model. The inaccuracies can cause glitches.
6952static int64_t in_get_mmap_time_offset() {
6953 const int32_t kDefaultOffsetMicros = 0;
6954 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006955 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006956 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6957 return mmap_time_offset_micros * (int64_t)1000;
6958}
6959
Haynes Mathew George16081042017-05-31 17:16:49 -07006960static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6961 int32_t min_size_frames,
6962 struct audio_mmap_buffer_info *info)
6963{
6964 struct stream_in *in = (struct stream_in *)stream;
6965 struct audio_device *adev = in->dev;
6966 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006967 unsigned int offset1 = 0;
6968 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006969 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006970 uint32_t mmap_size = 0;
6971 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006972
6973 pthread_mutex_lock(&adev->lock);
6974 ALOGV("%s in %p", __func__, in);
6975
Sharad Sanglec6f32552018-05-04 16:15:38 +05306976 if (CARD_STATUS_OFFLINE == in->card_status||
6977 CARD_STATUS_OFFLINE == adev->card_status) {
6978 ALOGW("in->card_status or adev->card_status offline, try again");
6979 ret = -EIO;
6980 goto exit;
6981 }
6982
Haynes Mathew George16081042017-05-31 17:16:49 -07006983 if (info == NULL || min_size_frames == 0) {
6984 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6985 ret = -EINVAL;
6986 goto exit;
6987 }
6988 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6989 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6990 ALOGV("%s in %p", __func__, in);
6991 ret = -ENOSYS;
6992 goto exit;
6993 }
6994 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6995 if (in->pcm_device_id < 0) {
6996 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6997 __func__, in->pcm_device_id, in->usecase);
6998 ret = -EINVAL;
6999 goto exit;
7000 }
7001
7002 adjust_mmap_period_count(&in->config, min_size_frames);
7003
7004 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7005 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7006 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7007 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307008 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307009 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7010 in->card_status = CARD_STATUS_OFFLINE;
7011 adev->card_status = CARD_STATUS_OFFLINE;
7012 ret = -EIO;
7013 goto exit;
7014 }
7015
Haynes Mathew George16081042017-05-31 17:16:49 -07007016 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7017 step = "open";
7018 ret = -ENODEV;
7019 goto exit;
7020 }
7021
7022 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7023 if (ret < 0) {
7024 step = "begin";
7025 goto exit;
7026 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007027
Arun Mirpuri5d170872019-03-26 13:21:31 -07007028 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7029 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7030 info->burst_size_frames = in->config.period_size;
7031 ret = platform_get_mmap_data_fd(adev->platform,
7032 in->pcm_device_id, 1 /*capture*/,
7033 &info->shared_memory_fd,
7034 &mmap_size);
7035 if (ret < 0) {
7036 // Fall back to non exclusive mode
7037 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7038 } else {
7039 if (mmap_size < buffer_size) {
7040 step = "mmap";
7041 goto exit;
7042 }
7043 // FIXME: indicate exclusive mode support by returning a negative buffer size
7044 info->buffer_size_frames *= -1;
7045 }
7046
7047 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007048
7049 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7050 if (ret < 0) {
7051 step = "commit";
7052 goto exit;
7053 }
7054
Phil Burke0a86d12019-02-16 22:28:11 -08007055 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7056
Haynes Mathew George16081042017-05-31 17:16:49 -07007057 in->standby = false;
7058 ret = 0;
7059
7060 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7061 __func__, info->shared_memory_address, info->buffer_size_frames);
7062
7063exit:
7064 if (ret != 0) {
7065 if (in->pcm == NULL) {
7066 ALOGE("%s: %s - %d", __func__, step, ret);
7067 } else {
7068 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7069 pcm_close(in->pcm);
7070 in->pcm = NULL;
7071 }
7072 }
7073 pthread_mutex_unlock(&adev->lock);
7074 return ret;
7075}
7076
7077static int in_get_mmap_position(const struct audio_stream_in *stream,
7078 struct audio_mmap_position *position)
7079{
7080 struct stream_in *in = (struct stream_in *)stream;
7081 ALOGVV("%s", __func__);
7082 if (position == NULL) {
7083 return -EINVAL;
7084 }
7085 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7086 return -ENOSYS;
7087 }
7088 if (in->pcm == NULL) {
7089 return -ENOSYS;
7090 }
7091 struct timespec ts = { 0, 0 };
7092 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7093 if (ret < 0) {
7094 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7095 return ret;
7096 }
Phil Burke0a86d12019-02-16 22:28:11 -08007097 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7098 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007099 return 0;
7100}
7101
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307102static int in_get_active_microphones(const struct audio_stream_in *stream,
7103 struct audio_microphone_characteristic_t *mic_array,
7104 size_t *mic_count) {
7105 struct stream_in *in = (struct stream_in *)stream;
7106 struct audio_device *adev = in->dev;
7107 ALOGVV("%s", __func__);
7108
7109 lock_input_stream(in);
7110 pthread_mutex_lock(&adev->lock);
7111 int ret = platform_get_active_microphones(adev->platform,
7112 audio_channel_count_from_in_mask(in->channel_mask),
7113 in->usecase, mic_array, mic_count);
7114 pthread_mutex_unlock(&adev->lock);
7115 pthread_mutex_unlock(&in->lock);
7116
7117 return ret;
7118}
7119
7120static int adev_get_microphones(const struct audio_hw_device *dev,
7121 struct audio_microphone_characteristic_t *mic_array,
7122 size_t *mic_count) {
7123 struct audio_device *adev = (struct audio_device *)dev;
7124 ALOGVV("%s", __func__);
7125
7126 pthread_mutex_lock(&adev->lock);
7127 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7128 pthread_mutex_unlock(&adev->lock);
7129
7130 return ret;
7131}
juyuchendb308c22019-01-21 11:57:17 -07007132
7133static void in_update_sink_metadata(struct audio_stream_in *stream,
7134 const struct sink_metadata *sink_metadata) {
7135
7136 if (stream == NULL
7137 || sink_metadata == NULL
7138 || sink_metadata->tracks == NULL) {
7139 return;
7140 }
7141
7142 int error = 0;
7143 struct stream_in *in = (struct stream_in *)stream;
7144 struct audio_device *adev = in->dev;
7145 audio_devices_t device = AUDIO_DEVICE_NONE;
7146
7147 if (sink_metadata->track_count != 0)
7148 device = sink_metadata->tracks->dest_device;
7149
7150 lock_input_stream(in);
7151 pthread_mutex_lock(&adev->lock);
7152 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
7153
7154 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
7155 && device != AUDIO_DEVICE_NONE
7156 && adev->voice_tx_output != NULL) {
7157 /* Use the rx device from afe-proxy record to route voice call because
7158 there is no routing if tx device is on primary hal and rx device
7159 is on other hal during voice call. */
7160 adev->voice_tx_output->devices = device;
7161
7162 if (!voice_is_call_state_active(adev)) {
7163 if (adev->mode == AUDIO_MODE_IN_CALL) {
7164 adev->current_call_output = adev->voice_tx_output;
7165 error = voice_start_call(adev);
7166 if (error != 0)
7167 ALOGE("%s: start voice call failed %d", __func__, error);
7168 }
7169 } else {
7170 adev->current_call_output = adev->voice_tx_output;
7171 voice_update_devices_for_all_voice_usecases(adev);
7172 }
7173 }
7174
7175 pthread_mutex_unlock(&adev->lock);
7176 pthread_mutex_unlock(&in->lock);
7177}
7178
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307179int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007180 audio_io_handle_t handle,
7181 audio_devices_t devices,
7182 audio_output_flags_t flags,
7183 struct audio_config *config,
7184 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007185 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007186{
7187 struct audio_device *adev = (struct audio_device *)dev;
7188 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307189 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007190 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007191 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307192 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007193 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7194 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7195 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7196 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007197 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007198 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7199 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007200 bool force_haptic_path =
7201 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007202 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007203
kunleizdff872d2018-08-20 14:40:33 +08007204 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007205 is_usb_dev = false;
7206 devices = AUDIO_DEVICE_OUT_SPEAKER;
7207 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7208 __func__, devices);
7209 }
7210
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007211 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307212
Rahul Sharma99770982019-03-06 17:05:26 +05307213 pthread_mutex_lock(&adev->lock);
7214 if (out_get_stream(adev, handle) != NULL) {
7215 ALOGW("%s, output stream already opened", __func__);
7216 ret = -EEXIST;
7217 }
7218 pthread_mutex_unlock(&adev->lock);
7219 if (ret)
7220 return ret;
7221
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007222 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7223
Mingming Yin3a941d42016-02-17 18:08:05 -08007224 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007225 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7226 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307227
7228
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007229 if (!out) {
7230 return -ENOMEM;
7231 }
7232
Haynes Mathew George204045b2015-02-25 20:32:03 -08007233 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007234 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307235 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007236 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007237 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007239 if (devices == AUDIO_DEVICE_NONE)
7240 devices = AUDIO_DEVICE_OUT_SPEAKER;
7241
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007242 out->flags = flags;
7243 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007244 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007245 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007246 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307247 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307248 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7249 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7250 else
7251 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007252 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007253 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007254 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307255 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307256 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307257 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007258 out->hal_output_suspend_supported = 0;
7259 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307260 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307261 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307262 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007263
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307264 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307265 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007266 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7267
Aalique Grahame22e49102018-12-18 14:23:57 -08007268 if (direct_dev &&
7269 (audio_is_linear_pcm(out->format) ||
7270 config->format == AUDIO_FORMAT_DEFAULT) &&
7271 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7272 audio_format_t req_format = config->format;
7273 audio_channel_mask_t req_channel_mask = config->channel_mask;
7274 uint32_t req_sample_rate = config->sample_rate;
7275
7276 pthread_mutex_lock(&adev->lock);
7277 if (is_hdmi) {
7278 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7279 ret = read_hdmi_sink_caps(out);
7280 if (config->sample_rate == 0)
7281 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7282 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7283 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7284 if (config->format == AUDIO_FORMAT_DEFAULT)
7285 config->format = AUDIO_FORMAT_PCM_16_BIT;
7286 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007287 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7288 &config->format,
7289 &out->supported_formats[0],
7290 MAX_SUPPORTED_FORMATS,
7291 &config->channel_mask,
7292 &out->supported_channel_masks[0],
7293 MAX_SUPPORTED_CHANNEL_MASKS,
7294 &config->sample_rate,
7295 &out->supported_sample_rates[0],
7296 MAX_SUPPORTED_SAMPLE_RATES);
7297 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007298 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007299
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007300 pthread_mutex_unlock(&adev->lock);
7301 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007302 if (ret == -ENOSYS) {
7303 /* ignore and go with default */
7304 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007305 }
7306 // For MMAP NO IRQ, allow conversions in ADSP
7307 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7308 goto error_open;
7309 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007310 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007311 goto error_open;
7312 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007313
7314 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7315 config->sample_rate = req_sample_rate;
7316 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7317 config->channel_mask = req_channel_mask;
7318 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7319 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007320 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007321
7322 out->sample_rate = config->sample_rate;
7323 out->channel_mask = config->channel_mask;
7324 out->format = config->format;
7325 if (is_hdmi) {
7326 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7327 out->config = pcm_config_hdmi_multi;
7328 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7329 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7330 out->config = pcm_config_mmap_playback;
7331 out->stream.start = out_start;
7332 out->stream.stop = out_stop;
7333 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7334 out->stream.get_mmap_position = out_get_mmap_position;
7335 } else {
7336 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7337 out->config = pcm_config_hifi;
7338 }
7339
7340 out->config.rate = out->sample_rate;
7341 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7342 if (is_hdmi) {
7343 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7344 audio_bytes_per_sample(out->format));
7345 }
7346 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007347 }
7348
Derek Chenf6318be2017-06-12 17:16:24 -04007349 /* validate bus device address */
7350 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7351 /* extract car audio stream index */
7352 out->car_audio_stream =
7353 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7354 if (out->car_audio_stream < 0) {
7355 ALOGE("%s: invalid car audio stream %x",
7356 __func__, out->car_audio_stream);
7357 ret = -EINVAL;
7358 goto error_open;
7359 }
7360 /* save car audio stream and address for bus device */
7361 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
7362 ALOGV("%s: address %s, car_audio_stream %x",
7363 __func__, out->address, out->car_audio_stream);
7364 }
7365
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007366 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007367 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007368 if (!voice_extn_is_compress_voip_supported()) {
7369 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7370 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007371 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7372 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007373 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7374 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007375 out->volume_l = INVALID_OUT_VOLUME;
7376 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007377
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007378 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007379 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007380 uint32_t channel_count =
7381 audio_channel_count_from_out_mask(out->channel_mask);
7382 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7383 out->sample_rate, out->format,
7384 channel_count, false);
7385 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7386 if (frame_size != 0)
7387 out->config.period_size = buffer_size / frame_size;
7388 else
7389 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007390 }
7391 } else {
7392 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7393 voice_extn_compress_voip_is_active(out->dev)) &&
7394 (voice_extn_compress_voip_is_config_supported(config))) {
7395 ret = voice_extn_compress_voip_open_output_stream(out);
7396 if (ret != 0) {
7397 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7398 __func__, ret);
7399 goto error_open;
7400 }
Sujin Panickerbd95e0a2019-09-16 18:28:06 +05307401 } else {
7402 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7403 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007404 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007405 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007406 } else if (audio_is_linear_pcm(out->format) &&
7407 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7408 out->channel_mask = config->channel_mask;
7409 out->sample_rate = config->sample_rate;
7410 out->format = config->format;
7411 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7412 // does this change?
7413 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7414 out->config.rate = config->sample_rate;
7415 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7416 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7417 audio_bytes_per_sample(config->format));
7418 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007419 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307420 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307421 pthread_mutex_lock(&adev->lock);
7422 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7423 pthread_mutex_unlock(&adev->lock);
7424
7425 // reject offload during card offline to allow
7426 // fallback to s/w paths
7427 if (offline) {
7428 ret = -ENODEV;
7429 goto error_open;
7430 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007431
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007432 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7433 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7434 ALOGE("%s: Unsupported Offload information", __func__);
7435 ret = -EINVAL;
7436 goto error_open;
7437 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007438
Atul Khare3fa6e542017-08-09 00:56:17 +05307439 if (config->offload_info.format == 0)
7440 config->offload_info.format = config->format;
7441 if (config->offload_info.sample_rate == 0)
7442 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007443
Mingming Yin90310102013-11-13 16:57:00 -08007444 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307445 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007446 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007447 ret = -EINVAL;
7448 goto error_open;
7449 }
7450
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007451 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7452 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7453 (audio_extn_passthru_is_passthrough_stream(out)) &&
7454 !((config->sample_rate == 48000) ||
7455 (config->sample_rate == 96000) ||
7456 (config->sample_rate == 192000))) {
7457 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7458 __func__, config->sample_rate, config->offload_info.format);
7459 ret = -EINVAL;
7460 goto error_open;
7461 }
7462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007463 out->compr_config.codec = (struct snd_codec *)
7464 calloc(1, sizeof(struct snd_codec));
7465
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007466 if (!out->compr_config.codec) {
7467 ret = -ENOMEM;
7468 goto error_open;
7469 }
7470
Dhananjay Kumarac341582017-02-23 23:42:25 +05307471 out->stream.pause = out_pause;
7472 out->stream.resume = out_resume;
7473 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307474 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307475 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007476 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307477 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007478 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307479 } else {
7480 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7481 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007482 }
vivek mehta446c3962015-09-14 10:57:35 -07007483
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307484 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7485 ALOGD("%s: Setting latency mode to true", __func__);
7486 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
7487 }
7488
vivek mehta446c3962015-09-14 10:57:35 -07007489 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007490 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7491 config->format == 0 && config->sample_rate == 0 &&
7492 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007493 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007494 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7495 } else {
7496 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7497 ret = -EEXIST;
7498 goto error_open;
7499 }
vivek mehta446c3962015-09-14 10:57:35 -07007500 }
7501
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007502 if (config->offload_info.channel_mask)
7503 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007504 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007505 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007506 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007507 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307508 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007509 ret = -EINVAL;
7510 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007511 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007512
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007513 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007514 out->sample_rate = config->offload_info.sample_rate;
7515
Mingming Yin3ee55c62014-08-04 14:23:35 -07007516 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007517
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307518 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307519 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307520 audio_extn_dolby_send_ddp_endp_params(adev);
7521 audio_extn_dolby_set_dmid(adev);
7522 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007523
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007524 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007525 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007526 out->compr_config.codec->bit_rate =
7527 config->offload_info.bit_rate;
7528 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307529 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007530 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307531 /* Update bit width only for non passthrough usecases.
7532 * For passthrough usecases, the output will always be opened @16 bit
7533 */
7534 if (!audio_extn_passthru_is_passthrough_stream(out))
7535 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307536
7537 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7538 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7539 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7540
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007541 /*TODO: Do we need to change it for passthrough */
7542 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007543
Manish Dewangana6fc5442015-08-24 20:30:31 +05307544 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7545 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307546 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307547 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307548 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7549 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307550
7551 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7552 AUDIO_FORMAT_PCM) {
7553
7554 /*Based on platform support, configure appropriate alsa format for corresponding
7555 *hal input format.
7556 */
7557 out->compr_config.codec->format = hal_format_to_alsa(
7558 config->offload_info.format);
7559
Ashish Jain83a6cc22016-06-28 14:34:17 +05307560 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307561 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307562 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307563
Dhananjay Kumarac341582017-02-23 23:42:25 +05307564 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307565 *hal input format and alsa format might differ based on platform support.
7566 */
7567 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307568 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307569
7570 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7571
Deeraj Soman65358ab2019-02-07 15:40:49 +05307572 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7573 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7574 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7575
Ashish Jainf1eaa582016-05-23 20:54:24 +05307576 /* Check if alsa session is configured with the same format as HAL input format,
7577 * if not then derive correct fragment size needed to accomodate the
7578 * conversion of HAL input format to alsa format.
7579 */
7580 audio_extn_utils_update_direct_pcm_fragment_size(out);
7581
7582 /*if hal input and output fragment size is different this indicates HAL input format is
7583 *not same as the alsa format
7584 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307585 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307586 /*Allocate a buffer to convert input data to the alsa configured format.
7587 *size of convert buffer is equal to the size required to hold one fragment size
7588 *worth of pcm data, this is because flinger does not write more than fragment_size
7589 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307590 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7591 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307592 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7593 ret = -ENOMEM;
7594 goto error_open;
7595 }
7596 }
7597 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7598 out->compr_config.fragment_size =
7599 audio_extn_passthru_get_buffer_size(&config->offload_info);
7600 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7601 } else {
7602 out->compr_config.fragment_size =
7603 platform_get_compress_offload_buffer_size(&config->offload_info);
7604 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7605 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007606
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307607 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7608 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7609 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007610 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307611 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007612
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307613 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7614 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7615 }
7616
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007617 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7618 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007619
Manish Dewangan69426c82017-01-30 17:35:36 +05307620 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7621 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7622 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7623 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7624 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7625 } else {
7626 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7627 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007628
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307629 memset(&out->channel_map_param, 0,
7630 sizeof(struct audio_out_channel_map_param));
7631
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007632 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307633 out->send_next_track_params = false;
7634 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007635 out->offload_state = OFFLOAD_STATE_IDLE;
7636 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007637 out->writeAt.tv_sec = 0;
7638 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007639
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007640 audio_extn_dts_create_state_notifier_node(out->usecase);
7641
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007642 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7643 __func__, config->offload_info.version,
7644 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307645
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307646 /* Check if DSD audio format is supported in codec
7647 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307648 */
7649
7650 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307651 (!platform_check_codec_dsd_support(adev->platform) ||
7652 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307653 ret = -EINVAL;
7654 goto error_open;
7655 }
7656
Ashish Jain5106d362016-05-11 19:23:33 +05307657 /* Disable gapless if any of the following is true
7658 * passthrough playback
7659 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307660 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307661 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307662 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307663 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007664 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307665 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307666 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307667 check_and_set_gapless_mode(adev, false);
7668 } else
7669 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007670
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307671 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007672 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7673 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307674 if (config->format == AUDIO_FORMAT_DSD) {
7675 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7676 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7677 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007678
7679 create_offload_callback_thread(out);
7680
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007681 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007682 switch (config->sample_rate) {
7683 case 0:
7684 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7685 break;
7686 case 8000:
7687 case 16000:
7688 case 48000:
7689 out->sample_rate = config->sample_rate;
7690 break;
7691 default:
7692 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7693 config->sample_rate);
7694 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7695 ret = -EINVAL;
7696 goto error_open;
7697 }
7698 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7699 switch (config->channel_mask) {
7700 case AUDIO_CHANNEL_NONE:
7701 case AUDIO_CHANNEL_OUT_STEREO:
7702 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7703 break;
7704 default:
7705 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7706 config->channel_mask);
7707 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7708 ret = -EINVAL;
7709 goto error_open;
7710 }
7711 switch (config->format) {
7712 case AUDIO_FORMAT_DEFAULT:
7713 case AUDIO_FORMAT_PCM_16_BIT:
7714 out->format = AUDIO_FORMAT_PCM_16_BIT;
7715 break;
7716 default:
7717 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7718 config->format);
7719 config->format = AUDIO_FORMAT_PCM_16_BIT;
7720 ret = -EINVAL;
7721 goto error_open;
7722 }
7723
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307724 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007725 if (ret != 0) {
7726 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007727 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007728 goto error_open;
7729 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007730 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007731 switch (config->sample_rate) {
7732 case 0:
7733 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7734 break;
7735 case 8000:
7736 case 16000:
7737 case 48000:
7738 out->sample_rate = config->sample_rate;
7739 break;
7740 default:
7741 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7742 config->sample_rate);
7743 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7744 ret = -EINVAL;
7745 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007746 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007747 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7748 switch (config->channel_mask) {
7749 case AUDIO_CHANNEL_NONE:
7750 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7751 break;
7752 case AUDIO_CHANNEL_OUT_STEREO:
7753 out->channel_mask = config->channel_mask;
7754 break;
7755 default:
7756 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7757 config->channel_mask);
7758 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7759 ret = -EINVAL;
7760 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007761 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007762 switch (config->format) {
7763 case AUDIO_FORMAT_DEFAULT:
7764 out->format = AUDIO_FORMAT_PCM_16_BIT;
7765 break;
7766 case AUDIO_FORMAT_PCM_16_BIT:
7767 out->format = config->format;
7768 break;
7769 default:
7770 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7771 config->format);
7772 config->format = AUDIO_FORMAT_PCM_16_BIT;
7773 ret = -EINVAL;
7774 break;
7775 }
7776 if (ret != 0)
7777 goto error_open;
7778
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007779 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7780 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007781 out->config.rate = out->sample_rate;
7782 out->config.channels =
7783 audio_channel_count_from_out_mask(out->channel_mask);
7784 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007785 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007786 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307787 unsigned int channels = 0;
7788 /*Update config params to default if not set by the caller*/
7789 if (config->sample_rate == 0)
7790 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7791 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7792 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7793 if (config->format == AUDIO_FORMAT_DEFAULT)
7794 config->format = AUDIO_FORMAT_PCM_16_BIT;
7795
7796 channels = audio_channel_count_from_out_mask(out->channel_mask);
7797
Varun Balaraje49253e2017-07-06 19:48:56 +05307798 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7799 out->usecase = get_interactive_usecase(adev);
7800 out->config = pcm_config_low_latency;
7801 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307802 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007803 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7804 out->flags);
7805 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007806 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7807 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7808 out->config = pcm_config_mmap_playback;
7809 out->stream.start = out_start;
7810 out->stream.stop = out_stop;
7811 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7812 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307813 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7814 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007815 out->hal_output_suspend_supported =
7816 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7817 out->dynamic_pm_qos_config_supported =
7818 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7819 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007820 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7821 } else {
7822 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7823 //the mixer path will be a string similar to "low-latency-playback resume"
7824 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7825 strlcat(out->pm_qos_mixer_path,
7826 " resume", MAX_MIXER_PATH_LEN);
7827 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7828 out->pm_qos_mixer_path);
7829 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307830 out->config = pcm_config_low_latency;
7831 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7832 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7833 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307834 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7835 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7836 if (out->config.period_size <= 0) {
7837 ALOGE("Invalid configuration period size is not valid");
7838 ret = -EINVAL;
7839 goto error_open;
7840 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007841 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7842 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7843 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007844 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7845 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7846 out->config = pcm_config_haptics_audio;
7847 if (force_haptic_path)
7848 adev->haptics_config = pcm_config_haptics_audio;
7849 else
7850 adev->haptics_config = pcm_config_haptics;
7851
7852 out->config.channels =
7853 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7854
7855 if (force_haptic_path) {
7856 out->config.channels = 1;
7857 adev->haptics_config.channels = 1;
7858 } else
7859 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Derek Chenf6318be2017-06-12 17:16:24 -04007860 } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7861 ret = audio_extn_auto_hal_open_output_stream(out);
7862 if (ret) {
7863 ALOGE("%s: Failed to open output stream for bus device", __func__);
7864 ret = -EINVAL;
7865 goto error_open;
7866 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307867 } else {
7868 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007869 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7870 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307871 }
7872 out->hal_ip_format = format = out->format;
7873 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7874 out->hal_op_format = pcm_format_to_hal(out->config.format);
7875 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7876 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007877 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307878 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307879 if (out->hal_ip_format != out->hal_op_format) {
7880 uint32_t buffer_size = out->config.period_size *
7881 format_to_bitwidth_table[out->hal_op_format] *
7882 out->config.channels;
7883 out->convert_buffer = calloc(1, buffer_size);
7884 if (out->convert_buffer == NULL){
7885 ALOGE("Allocation failed for convert buffer for size %d",
7886 out->compr_config.fragment_size);
7887 ret = -ENOMEM;
7888 goto error_open;
7889 }
7890 ALOGD("Convert buffer allocated of size %d", buffer_size);
7891 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007892 }
7893
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007894 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7895 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307896
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007897 /* TODO remove this hardcoding and check why width is zero*/
7898 if (out->bit_width == 0)
7899 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307900 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007901 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007902 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307903 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307904 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007905 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007906 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7907 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007908 if(adev->primary_output == NULL)
7909 adev->primary_output = out;
7910 else {
7911 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007912 ret = -EEXIST;
7913 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007914 }
7915 }
7916
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007917 /* Check if this usecase is already existing */
7918 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007919 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7920 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007921 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007922 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007923 ret = -EEXIST;
7924 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007925 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007926
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007927 pthread_mutex_unlock(&adev->lock);
7928
7929 out->stream.common.get_sample_rate = out_get_sample_rate;
7930 out->stream.common.set_sample_rate = out_set_sample_rate;
7931 out->stream.common.get_buffer_size = out_get_buffer_size;
7932 out->stream.common.get_channels = out_get_channels;
7933 out->stream.common.get_format = out_get_format;
7934 out->stream.common.set_format = out_set_format;
7935 out->stream.common.standby = out_standby;
7936 out->stream.common.dump = out_dump;
7937 out->stream.common.set_parameters = out_set_parameters;
7938 out->stream.common.get_parameters = out_get_parameters;
7939 out->stream.common.add_audio_effect = out_add_audio_effect;
7940 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7941 out->stream.get_latency = out_get_latency;
7942 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007943#ifdef NO_AUDIO_OUT
7944 out->stream.write = out_write_for_no_output;
7945#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007946 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007947#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007948 out->stream.get_render_position = out_get_render_position;
7949 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007950 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007951
Haynes Mathew George16081042017-05-31 17:16:49 -07007952 if (out->realtime)
7953 out->af_period_multiplier = af_period_multiplier;
7954 else
7955 out->af_period_multiplier = 1;
7956
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007957 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007958 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007959 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007960
7961 config->format = out->stream.common.get_format(&out->stream.common);
7962 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7963 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307964 register_format(out->format, out->supported_formats);
7965 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7966 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007967
Aalique Grahame22e49102018-12-18 14:23:57 -08007968 out->error_log = error_log_create(
7969 ERROR_LOG_ENTRIES,
7970 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7971
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307972 /*
7973 By locking output stream before registering, we allow the callback
7974 to update stream's state only after stream's initial state is set to
7975 adev state.
7976 */
7977 lock_output_stream(out);
7978 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7979 pthread_mutex_lock(&adev->lock);
7980 out->card_status = adev->card_status;
7981 pthread_mutex_unlock(&adev->lock);
7982 pthread_mutex_unlock(&out->lock);
7983
Aalique Grahame22e49102018-12-18 14:23:57 -08007984 stream_app_type_cfg_init(&out->app_type_cfg);
7985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007986 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307987 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007988 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007989
7990 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7991 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7992 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007993 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307994 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007995 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007996 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307997 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
7998 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007999 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8000 out->usecase, PCM_PLAYBACK);
8001 hdlr_stream_cfg.flags = out->flags;
8002 hdlr_stream_cfg.type = PCM_PLAYBACK;
8003 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8004 &hdlr_stream_cfg);
8005 if (ret) {
8006 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8007 out->adsp_hdlr_stream_handle = NULL;
8008 }
8009 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308010 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8011 is_direct_passthough, false);
8012 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8013 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008014 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008015 if (ret < 0) {
8016 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8017 out->ip_hdlr_handle = NULL;
8018 }
8019 }
Derek Chenf939fb72018-11-13 13:34:41 -08008020
8021 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8022 calloc(1, sizeof(streams_output_ctxt_t));
8023 if (out_ctxt == NULL) {
8024 ALOGE("%s fail to allocate output ctxt", __func__);
8025 ret = -ENOMEM;
8026 goto error_open;
8027 }
8028 out_ctxt->output = out;
8029
8030 pthread_mutex_lock(&adev->lock);
8031 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8032 pthread_mutex_unlock(&adev->lock);
8033
Eric Laurent994a6932013-07-17 11:51:42 -07008034 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008035 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008036
8037error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308038 if (out->convert_buffer)
8039 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008040 free(out);
8041 *stream_out = NULL;
8042 ALOGD("%s: exit: ret %d", __func__, ret);
8043 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008044}
8045
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308046void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008047 struct audio_stream_out *stream)
8048{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008049 struct stream_out *out = (struct stream_out *)stream;
8050 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008051 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008052
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008053 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308054
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308055 // must deregister from sndmonitor first to prevent races
8056 // between the callback and close_stream
8057 audio_extn_snd_mon_unregister_listener(out);
8058
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008059 /* close adsp hdrl session before standby */
8060 if (out->adsp_hdlr_stream_handle) {
8061 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8062 if (ret)
8063 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8064 out->adsp_hdlr_stream_handle = NULL;
8065 }
8066
Manish Dewangan21a850a2017-08-14 12:03:55 +05308067 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008068 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8069 out->ip_hdlr_handle = NULL;
8070 }
8071
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008072 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308073 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008074 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308075 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308076 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008077 if(ret != 0)
8078 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8079 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008080 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008081 out_standby(&stream->common);
8082
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008083 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008084 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008085 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008086 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008087 if (out->compr_config.codec != NULL)
8088 free(out->compr_config.codec);
8089 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008090
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308091 out->a2dp_compress_mute = false;
8092
Varun Balaraje49253e2017-07-06 19:48:56 +05308093 if (is_interactive_usecase(out->usecase))
8094 free_interactive_usecase(adev, out->usecase);
8095
Ashish Jain83a6cc22016-06-28 14:34:17 +05308096 if (out->convert_buffer != NULL) {
8097 free(out->convert_buffer);
8098 out->convert_buffer = NULL;
8099 }
8100
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008101 if (adev->voice_tx_output == out)
8102 adev->voice_tx_output = NULL;
8103
Aalique Grahame22e49102018-12-18 14:23:57 -08008104 error_log_destroy(out->error_log);
8105 out->error_log = NULL;
8106
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308107 if (adev->primary_output == out)
8108 adev->primary_output = NULL;
8109
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008110 pthread_cond_destroy(&out->cond);
8111 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008112
8113 pthread_mutex_lock(&adev->lock);
8114 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8115 if (out_ctxt != NULL) {
8116 list_remove(&out_ctxt->list);
8117 free(out_ctxt);
8118 } else {
8119 ALOGW("%s, output stream already closed", __func__);
8120 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008121 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008122 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008123 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008124}
8125
8126static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8127{
8128 struct audio_device *adev = (struct audio_device *)dev;
8129 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008130 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008131 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008132 int ret;
8133 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008134 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008135 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008136
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008137 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008138 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008139
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308140 if (!parms)
8141 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308142
Derek Chen6f293672019-04-01 01:40:24 -07008143 /* notify adev and input/output streams on the snd card status */
8144 adev_snd_mon_cb((void *)adev, parms);
8145
8146 list_for_each(node, &adev->active_outputs_list) {
8147 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8148 streams_output_ctxt_t,
8149 list);
8150 out_snd_mon_cb((void *)out_ctxt->output, parms);
8151 }
8152
8153 list_for_each(node, &adev->active_inputs_list) {
8154 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8155 streams_input_ctxt_t,
8156 list);
8157 in_snd_mon_cb((void *)in_ctxt->input, parms);
8158 }
8159
Zhou Songd6d71752019-05-21 18:08:51 +08008160 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308161 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8162 if (ret >= 0) {
8163 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008164 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308165 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008166 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308167 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008168 audio_extn_sco_reset_configuration();
Kunlei Zhang136e6742019-08-27 16:33:29 +08008169 }
8170 }
8171
8172 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8173 if (ret>=0) {
8174 if (!strncmp(value, "false", 5) &&
8175 audio_extn_a2dp_source_is_suspended()) {
8176 struct audio_usecase *usecase;
8177 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008178 list_for_each(node, &adev->usecase_list) {
8179 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhang136e6742019-08-27 16:33:29 +08008180 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
8181 ((usecase->stream.in->device & ~AUDIO_DEVICE_BIT_IN) &
8182 AUDIO_DEVICE_IN_ALL_SCO)) {
8183 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Zhou Songd6d71752019-05-21 18:08:51 +08008184 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
Kunlei Zhang136e6742019-08-27 16:33:29 +08008185 select_devices(adev, usecase->id);
8186 }
Zhou Songd6d71752019-05-21 18:08:51 +08008187 }
8188 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308189 }
8190
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008191 status = voice_set_parameters(adev, parms);
8192 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008193 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008194
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008195 status = platform_set_parameters(adev->platform, parms);
8196 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008197 goto done;
8198
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008199 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8200 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008201 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008202 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8203 adev->bluetooth_nrec = true;
8204 else
8205 adev->bluetooth_nrec = false;
8206 }
8207
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008208 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8209 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008210 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8211 adev->screen_off = false;
8212 else
8213 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008214 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008215 }
8216
Eric Laurent4b084132018-10-19 17:33:43 -07008217 ret = str_parms_get_int(parms, "rotation", &val);
8218 if (ret >= 0) {
8219 bool reverse_speakers = false;
8220 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8221 switch (val) {
8222 // FIXME: note that the code below assumes that the speakers are in the correct placement
8223 // relative to the user when the device is rotated 90deg from its default rotation. This
8224 // assumption is device-specific, not platform-specific like this code.
8225 case 270:
8226 reverse_speakers = true;
8227 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8228 break;
8229 case 0:
8230 case 180:
8231 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8232 break;
8233 case 90:
8234 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8235 break;
8236 default:
8237 ALOGE("%s: unexpected rotation of %d", __func__, val);
8238 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008239 }
Eric Laurent4b084132018-10-19 17:33:43 -07008240 if (status == 0) {
8241 // check and set swap
8242 // - check if orientation changed and speaker active
8243 // - set rotation and cache the rotation value
8244 adev->camera_orientation =
8245 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8246 if (!audio_extn_is_maxx_audio_enabled())
8247 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8248 }
8249 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008250
Mingming Yin514a8bc2014-07-29 15:22:21 -07008251 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8252 if (ret >= 0) {
8253 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8254 adev->bt_wb_speech_enabled = true;
8255 else
8256 adev->bt_wb_speech_enabled = false;
8257 }
8258
Zhou Song12c29502019-03-16 10:37:18 +08008259 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8260 if (ret >= 0) {
8261 val = atoi(value);
8262 adev->swb_speech_mode = val;
8263 }
8264
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008265 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8266 if (ret >= 0) {
8267 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308268 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008269 if (audio_is_output_device(val) &&
8270 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008271 ALOGV("cache new ext disp type and edid");
8272 ret = platform_get_ext_disp_type(adev->platform);
8273 if (ret < 0) {
8274 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308275 } else {
8276 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008277 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308278 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008279 /*
8280 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8281 * Per AudioPolicyManager, USB device is higher priority than WFD.
8282 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8283 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8284 * starting voice call on USB
8285 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008286 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308287 if (ret >= 0)
8288 audio_extn_usb_add_device(device, atoi(value));
8289
Zhou Song6f862822017-11-06 17:27:57 +08008290 if (!audio_extn_usb_is_tunnel_supported()) {
8291 ALOGV("detected USB connect .. disable proxy");
8292 adev->allow_afe_proxy_usage = false;
8293 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008294 }
8295 }
8296
8297 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8298 if (ret >= 0) {
8299 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308300 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008301 /*
8302 * The HDMI / Displayport disconnect handling has been moved to
8303 * audio extension to ensure that its parameters are not
8304 * invalidated prior to updating sysfs of the disconnect event
8305 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8306 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308307 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008308 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308309 if (ret >= 0)
8310 audio_extn_usb_remove_device(device, atoi(value));
8311
Zhou Song6f862822017-11-06 17:27:57 +08008312 if (!audio_extn_usb_is_tunnel_supported()) {
8313 ALOGV("detected USB disconnect .. enable proxy");
8314 adev->allow_afe_proxy_usage = true;
8315 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008316 }
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05308317 if (audio_is_a2dp_out_device(device)) {
8318 struct audio_usecase *usecase;
8319 struct listnode *node;
8320 list_for_each(node, &adev->usecase_list) {
8321 usecase = node_to_item(node, struct audio_usecase, list);
8322 if (PCM_PLAYBACK == usecase->type && usecase->stream.out &&
8323 (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8324 usecase->stream.out->a2dp_compress_mute) {
8325 struct stream_out *out = usecase->stream.out;
8326 ALOGD("Unmuting the stream when Bt-A2dp disconnected and stream is mute");
8327 out->a2dp_compress_mute = false;
8328 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8329 }
8330 }
8331 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008332 }
8333
Aalique Grahame22e49102018-12-18 14:23:57 -08008334 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008335 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008336
8337 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008338 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308339 struct audio_usecase *usecase;
8340 struct listnode *node;
8341 list_for_each(node, &adev->usecase_list) {
8342 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308343 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07008344 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308345 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008346 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308347 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008348 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308349 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308350 ALOGD("Switching to speaker and muting the stream before select_devices");
8351 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308352 //force device switch to re configure encoder
8353 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308354 ALOGD("Unmuting the stream after select_devices");
8355 usecase->stream.out->a2dp_compress_mute = false;
8356 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 +05308357 audio_extn_a2dp_set_handoff_mode(false);
8358 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308359 break;
8360 }
8361 }
8362 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008363
8364 //handle vr audio setparam
8365 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8366 value, sizeof(value));
8367 if (ret >= 0) {
8368 ALOGI("Setting vr mode to be %s", value);
8369 if (!strncmp(value, "true", 4)) {
8370 adev->vr_audio_mode_enabled = true;
8371 ALOGI("Setting vr mode to true");
8372 } else if (!strncmp(value, "false", 5)) {
8373 adev->vr_audio_mode_enabled = false;
8374 ALOGI("Setting vr mode to false");
8375 } else {
8376 ALOGI("wrong vr mode set");
8377 }
8378 }
8379
Eric Laurent4b084132018-10-19 17:33:43 -07008380 //FIXME: to be replaced by proper video capture properties API
8381 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8382 if (ret >= 0) {
8383 int camera_facing = CAMERA_FACING_BACK;
8384 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8385 camera_facing = CAMERA_FACING_FRONT;
8386 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8387 camera_facing = CAMERA_FACING_BACK;
8388 else {
8389 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8390 goto done;
8391 }
8392 adev->camera_orientation =
8393 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8394 struct audio_usecase *usecase;
8395 struct listnode *node;
8396 list_for_each(node, &adev->usecase_list) {
8397 usecase = node_to_item(node, struct audio_usecase, list);
8398 struct stream_in *in = usecase->stream.in;
8399 if (usecase->type == PCM_CAPTURE && in != NULL &&
8400 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8401 select_devices(adev, in->usecase);
8402 }
8403 }
8404 }
8405
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308406 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008407done:
8408 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008409 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308410error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008411 ALOGV("%s: exit with code(%d)", __func__, status);
8412 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008413}
8414
8415static char* adev_get_parameters(const struct audio_hw_device *dev,
8416 const char *keys)
8417{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308418 ALOGD("%s:%s", __func__, keys);
8419
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008420 struct audio_device *adev = (struct audio_device *)dev;
8421 struct str_parms *reply = str_parms_create();
8422 struct str_parms *query = str_parms_create_str(keys);
8423 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308424 char value[256] = {0};
8425 int ret = 0;
8426
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008427 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008428 if (reply) {
8429 str_parms_destroy(reply);
8430 }
8431 if (query) {
8432 str_parms_destroy(query);
8433 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008434 ALOGE("adev_get_parameters: failed to create query or reply");
8435 return NULL;
8436 }
8437
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008438 //handle vr audio getparam
8439
8440 ret = str_parms_get_str(query,
8441 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8442 value, sizeof(value));
8443
8444 if (ret >= 0) {
8445 bool vr_audio_enabled = false;
8446 pthread_mutex_lock(&adev->lock);
8447 vr_audio_enabled = adev->vr_audio_mode_enabled;
8448 pthread_mutex_unlock(&adev->lock);
8449
8450 ALOGI("getting vr mode to %d", vr_audio_enabled);
8451
8452 if (vr_audio_enabled) {
8453 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8454 "true");
8455 goto exit;
8456 } else {
8457 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8458 "false");
8459 goto exit;
8460 }
8461 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008462
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008463 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008464 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008465 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008466 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008467 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308468 pthread_mutex_unlock(&adev->lock);
8469
Naresh Tannirud7205b62014-06-20 02:54:48 +05308470exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008471 str = str_parms_to_str(reply);
8472 str_parms_destroy(query);
8473 str_parms_destroy(reply);
8474
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308475 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008476 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008477}
8478
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008479static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008480{
8481 return 0;
8482}
8483
8484static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8485{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008486 int ret;
8487 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008488
8489 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8490
Haynes Mathew George5191a852013-09-11 14:19:36 -07008491 pthread_mutex_lock(&adev->lock);
8492 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008493 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008494 pthread_mutex_unlock(&adev->lock);
8495 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008496}
8497
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008498static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8499 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008500{
8501 return -ENOSYS;
8502}
8503
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008504static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8505 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008506{
8507 return -ENOSYS;
8508}
8509
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008510static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8511 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008512{
8513 return -ENOSYS;
8514}
8515
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008516static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8517 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008518{
8519 return -ENOSYS;
8520}
8521
8522static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8523{
8524 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008525 struct listnode *node;
8526 struct audio_usecase *usecase = NULL;
8527 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008528
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008529 pthread_mutex_lock(&adev->lock);
8530 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008531 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008532 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008533 if (voice_is_in_call(adev) &&
8534 (mode == AUDIO_MODE_NORMAL ||
8535 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008536 list_for_each(node, &adev->usecase_list) {
8537 usecase = node_to_item(node, struct audio_usecase, list);
8538 if (usecase->type == VOICE_CALL)
8539 break;
8540 }
8541 if (usecase &&
8542 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8543 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8544 true);
8545 if (ret != 0) {
8546 /* default service interval was successfully updated,
8547 reopen USB backend with new service interval */
8548 check_usecases_codec_backend(adev,
8549 usecase,
8550 usecase->out_snd_device);
8551 }
8552 }
8553
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008554 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008555 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008556 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008557 // restore device for other active usecases after stop call
8558 list_for_each(node, &adev->usecase_list) {
8559 usecase = node_to_item(node, struct audio_usecase, list);
8560 select_devices(adev, usecase->id);
8561 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008562 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008563 }
8564 pthread_mutex_unlock(&adev->lock);
8565 return 0;
8566}
8567
8568static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8569{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008570 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008571 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008572
8573 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008574 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008575 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008576
Derek Chend2530072014-11-24 12:39:14 -08008577 if (adev->ext_hw_plugin)
8578 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008579
8580 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008581 pthread_mutex_unlock(&adev->lock);
8582
8583 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008584}
8585
8586static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8587{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008588 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008589 return 0;
8590}
8591
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008592static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008593 const struct audio_config *config)
8594{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008595 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008596
Aalique Grahame22e49102018-12-18 14:23:57 -08008597 /* Don't know if USB HIFI in this context so use true to be conservative */
8598 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8599 true /*is_usb_hifi */) != 0)
8600 return 0;
8601
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008602 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8603 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008604}
8605
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008606static bool adev_input_allow_hifi_record(struct audio_device *adev,
8607 audio_devices_t devices,
8608 audio_input_flags_t flags,
8609 audio_source_t source) {
8610 const bool allowed = true;
8611
8612 if (!audio_is_usb_in_device(devices))
8613 return !allowed;
8614
8615 switch (flags) {
8616 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008617 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008618 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8619 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008620 default:
8621 return !allowed;
8622 }
8623
8624 switch (source) {
8625 case AUDIO_SOURCE_DEFAULT:
8626 case AUDIO_SOURCE_MIC:
8627 case AUDIO_SOURCE_UNPROCESSED:
8628 break;
8629 default:
8630 return !allowed;
8631 }
8632
8633 switch (adev->mode) {
8634 case 0:
8635 break;
8636 default:
8637 return !allowed;
8638 }
8639
8640 return allowed;
8641}
8642
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008643static int adev_update_voice_comm_input_stream(struct stream_in *in,
8644 struct audio_config *config)
8645{
8646 bool valid_rate = (config->sample_rate == 8000 ||
8647 config->sample_rate == 16000 ||
8648 config->sample_rate == 32000 ||
8649 config->sample_rate == 48000);
8650 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8651
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008652 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008653 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008654 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8655 in->config = default_pcm_config_voip_copp;
8656 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8657 DEFAULT_VOIP_BUF_DURATION_MS,
8658 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008659 } else {
8660 ALOGW("%s No valid input in voip, use defaults"
8661 "sample rate %u, channel mask 0x%X",
8662 __func__, config->sample_rate, in->channel_mask);
8663 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008664 in->config.rate = config->sample_rate;
8665 in->sample_rate = config->sample_rate;
8666 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008667 //XXX needed for voice_extn_compress_voip_open_input_stream
8668 in->config.rate = config->sample_rate;
8669 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathacd1de7d2019-08-23 15:13:46 +05308670 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008671 voice_extn_compress_voip_is_active(in->dev)) &&
8672 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8673 valid_rate && valid_ch) {
8674 voice_extn_compress_voip_open_input_stream(in);
8675 // update rate entries to match config from AF
8676 in->config.rate = config->sample_rate;
8677 in->sample_rate = config->sample_rate;
8678 } else {
8679 ALOGW("%s compress voip not active, use defaults", __func__);
8680 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008681 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008682 return 0;
8683}
8684
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008685static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008686 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008687 audio_devices_t devices,
8688 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008689 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308690 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008691 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008692 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008693{
8694 struct audio_device *adev = (struct audio_device *)dev;
8695 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008696 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008697 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008698 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308699 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008700 bool is_usb_dev = audio_is_usb_in_device(devices);
8701 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8702 devices,
8703 flags,
8704 source);
Andy Hung94320602018-10-29 18:31:12 -07008705 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8706 " sample_rate %u, channel_mask %#x, format %#x",
8707 __func__, flags, is_usb_dev, may_use_hifi_record,
8708 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308709
kunleizdff872d2018-08-20 14:40:33 +08008710 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008711 is_usb_dev = false;
8712 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8713 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8714 __func__, devices);
8715 }
8716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008717 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008718
8719 if (!(is_usb_dev && may_use_hifi_record)) {
8720 if (config->sample_rate == 0)
8721 config->sample_rate = 48000;
8722 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8723 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8724 if (config->format == AUDIO_FORMAT_DEFAULT)
8725 config->format = AUDIO_FORMAT_PCM_16_BIT;
8726
8727 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8728
Aalique Grahame22e49102018-12-18 14:23:57 -08008729 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8730 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008731 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308732 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008733
Rahul Sharma99770982019-03-06 17:05:26 +05308734 pthread_mutex_lock(&adev->lock);
8735 if (in_get_stream(adev, handle) != NULL) {
8736 ALOGW("%s, input stream already opened", __func__);
8737 ret = -EEXIST;
8738 }
8739 pthread_mutex_unlock(&adev->lock);
8740 if (ret)
8741 return ret;
8742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008743 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008744
8745 if (!in) {
8746 ALOGE("failed to allocate input stream");
8747 return -ENOMEM;
8748 }
8749
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308750 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308751 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8752 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008753 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008754 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008756 in->stream.common.get_sample_rate = in_get_sample_rate;
8757 in->stream.common.set_sample_rate = in_set_sample_rate;
8758 in->stream.common.get_buffer_size = in_get_buffer_size;
8759 in->stream.common.get_channels = in_get_channels;
8760 in->stream.common.get_format = in_get_format;
8761 in->stream.common.set_format = in_set_format;
8762 in->stream.common.standby = in_standby;
8763 in->stream.common.dump = in_dump;
8764 in->stream.common.set_parameters = in_set_parameters;
8765 in->stream.common.get_parameters = in_get_parameters;
8766 in->stream.common.add_audio_effect = in_add_audio_effect;
8767 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8768 in->stream.set_gain = in_set_gain;
8769 in->stream.read = in_read;
8770 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008771 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308772 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008773 in->stream.set_microphone_direction = in_set_microphone_direction;
8774 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008775 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008776
8777 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008778 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008779 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008780 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008781 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008782 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008783 in->bit_width = 16;
8784 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008785 in->direction = MIC_DIRECTION_UNSPECIFIED;
8786 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08008787 list_init(&in->aec_list);
8788 list_init(&in->ns_list);
Haynes Mathew George46740472017-10-27 18:40:12 -07008789
Andy Hung94320602018-10-29 18:31:12 -07008790 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008791 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8792 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8793 /* Force channel config requested to mono if incall
8794 record is being requested for only uplink/downlink */
8795 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8796 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8797 ret = -EINVAL;
8798 goto err_open;
8799 }
8800 }
8801
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008802 if (is_usb_dev && may_use_hifi_record) {
8803 /* HiFi record selects an appropriate format, channel, rate combo
8804 depending on sink capabilities*/
8805 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8806 &config->format,
8807 &in->supported_formats[0],
8808 MAX_SUPPORTED_FORMATS,
8809 &config->channel_mask,
8810 &in->supported_channel_masks[0],
8811 MAX_SUPPORTED_CHANNEL_MASKS,
8812 &config->sample_rate,
8813 &in->supported_sample_rates[0],
8814 MAX_SUPPORTED_SAMPLE_RATES);
8815 if (ret != 0) {
8816 ret = -EINVAL;
8817 goto err_open;
8818 }
8819 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008820 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308821 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308822 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8823 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8824 in->config.format = PCM_FORMAT_S32_LE;
8825 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308826 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8827 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8828 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8829 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8830 bool ret_error = false;
8831 in->bit_width = 24;
8832 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8833 from HAL is 24_packed and 8_24
8834 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8835 24_packed return error indicating supported format is 24_packed
8836 *> In case of any other source requesting 24 bit or float return error
8837 indicating format supported is 16 bit only.
8838
8839 on error flinger will retry with supported format passed
8840 */
8841 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8842 (source != AUDIO_SOURCE_CAMCORDER)) {
8843 config->format = AUDIO_FORMAT_PCM_16_BIT;
8844 if (config->sample_rate > 48000)
8845 config->sample_rate = 48000;
8846 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008847 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8848 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308849 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8850 ret_error = true;
8851 }
8852
8853 if (ret_error) {
8854 ret = -EINVAL;
8855 goto err_open;
8856 }
8857 }
8858
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008859 in->channel_mask = config->channel_mask;
8860 in->format = config->format;
8861
8862 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308863
8864 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8865 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8866 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8867 else {
8868 ret = -EINVAL;
8869 goto err_open;
8870 }
8871 }
8872
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008873 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308874 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
8875 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008876 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8877 is_low_latency = true;
8878#if LOW_LATENCY_CAPTURE_USE_CASE
8879 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8880#endif
8881 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008882 if (!in->realtime) {
8883 in->config = pcm_config_audio_capture;
8884 frame_size = audio_stream_in_frame_size(&in->stream);
8885 buffer_size = get_input_buffer_size(config->sample_rate,
8886 config->format,
8887 channel_count,
8888 is_low_latency);
8889 in->config.period_size = buffer_size / frame_size;
8890 in->config.rate = config->sample_rate;
8891 in->af_period_multiplier = 1;
8892 } else {
8893 // period size is left untouched for rt mode playback
8894 in->config = pcm_config_audio_capture_rt;
8895 in->af_period_multiplier = af_period_multiplier;
8896 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008897 }
8898
8899 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8900 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8901 in->realtime = 0;
8902 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8903 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008904 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008905 in->stream.start = in_start;
8906 in->stream.stop = in_stop;
8907 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8908 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008909 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8910 } else if (in->realtime) {
8911 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008912 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008913 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008914 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008915 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8916 in->config = pcm_config_audio_capture;
8917 frame_size = audio_stream_in_frame_size(&in->stream);
8918 buffer_size = get_input_buffer_size(config->sample_rate,
8919 config->format,
8920 channel_count,
8921 false /*is_low_latency*/);
8922 in->config.period_size = buffer_size / frame_size;
8923 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008924 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008925 switch (config->format) {
8926 case AUDIO_FORMAT_PCM_32_BIT:
8927 in->bit_width = 32;
8928 break;
8929 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8930 case AUDIO_FORMAT_PCM_8_24_BIT:
8931 in->bit_width = 24;
8932 break;
8933 default:
8934 in->bit_width = 16;
8935 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008936 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308937 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008938 if (config->sample_rate == 0)
8939 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8940 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8941 config->sample_rate != 8000) {
8942 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8943 ret = -EINVAL;
8944 goto err_open;
8945 }
8946 if (config->format == AUDIO_FORMAT_DEFAULT)
8947 config->format = AUDIO_FORMAT_PCM_16_BIT;
8948 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8949 config->format = AUDIO_FORMAT_PCM_16_BIT;
8950 ret = -EINVAL;
8951 goto err_open;
8952 }
8953
8954 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8955 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008956 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008957 in->af_period_multiplier = 1;
8958 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8959 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8960 (config->sample_rate == 8000 ||
8961 config->sample_rate == 16000 ||
8962 config->sample_rate == 32000 ||
8963 config->sample_rate == 48000) &&
8964 channel_count == 1) {
8965 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8966 in->config = pcm_config_audio_capture;
8967 frame_size = audio_stream_in_frame_size(&in->stream);
8968 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8969 config->sample_rate,
8970 config->format,
8971 channel_count, false /*is_low_latency*/);
8972 in->config.period_size = buffer_size / frame_size;
8973 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8974 in->config.rate = config->sample_rate;
8975 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008976 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308977 int ret_val;
8978 pthread_mutex_lock(&adev->lock);
8979 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8980 in, config, &channel_mask_updated);
8981 pthread_mutex_unlock(&adev->lock);
8982
8983 if (!ret_val) {
8984 if (channel_mask_updated == true) {
8985 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8986 __func__, config->channel_mask);
8987 ret = -EINVAL;
8988 goto err_open;
8989 }
8990 ALOGD("%s: created multi-channel session succesfully",__func__);
8991 } else if (audio_extn_compr_cap_enabled() &&
8992 audio_extn_compr_cap_format_supported(config->format) &&
8993 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8994 audio_extn_compr_cap_init(in);
8995 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05308996 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308997 if (ret)
8998 goto err_open;
8999 } else {
9000 in->config = pcm_config_audio_capture;
9001 in->config.rate = config->sample_rate;
9002 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309003 in->format = config->format;
9004 frame_size = audio_stream_in_frame_size(&in->stream);
9005 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07009006 config->format,
9007 channel_count,
9008 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02009009 /* prevent division-by-zero */
9010 if (frame_size == 0) {
9011 ALOGE("%s: Error frame_size==0", __func__);
9012 ret = -EINVAL;
9013 goto err_open;
9014 }
9015
Revathi Uddarajud2634032017-12-07 14:42:34 +05309016 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009017 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009018
Revathi Uddarajud2634032017-12-07 14:42:34 +05309019 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9020 /* optionally use VOIP usecase depending on config(s) */
9021 ret = adev_update_voice_comm_input_stream(in, config);
9022 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009023
Revathi Uddarajud2634032017-12-07 14:42:34 +05309024 if (ret) {
9025 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9026 goto err_open;
9027 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009028 }
Samyak Jainc37062f2019-04-25 18:41:06 +05309029 if (audio_extn_is_concurrent_capture_enabled()) {
9030 /* Acquire lock to avoid two concurrent use cases initialized to
9031 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009032
Samyak Jainc37062f2019-04-25 18:41:06 +05309033 if (in->usecase == USECASE_AUDIO_RECORD) {
9034 pthread_mutex_lock(&adev->lock);
9035 if (!(adev->pcm_record_uc_state)) {
9036 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9037 adev->pcm_record_uc_state = 1;
9038 pthread_mutex_unlock(&adev->lock);
9039 } else {
9040 pthread_mutex_unlock(&adev->lock);
9041 /* Assign compress record use case for second record */
9042 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9043 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9044 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9045 if (audio_extn_cin_applicable_stream(in)) {
9046 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309047 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309048 if (ret)
9049 goto err_open;
9050 }
9051 }
9052 }
kunleiz28c73e72019-03-27 17:24:04 +08009053 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009054 }
Ramjee Singh8b09cc12019-08-21 16:31:33 +05309055 if (audio_extn_ssr_get_stream() != in)
9056 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009057
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009058 in->sample_rate = in->config.rate;
9059
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309060 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9061 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009062 devices, flags, in->format,
9063 in->sample_rate, in->bit_width,
9064 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309065 register_format(in->format, in->supported_formats);
9066 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9067 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309068
Aalique Grahame22e49102018-12-18 14:23:57 -08009069 in->error_log = error_log_create(
9070 ERROR_LOG_ENTRIES,
9071 1000000000 /* aggregate consecutive identical errors within one second */);
9072
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009073 /* This stream could be for sound trigger lab,
9074 get sound trigger pcm if present */
9075 audio_extn_sound_trigger_check_and_get_session(in);
9076
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309077 lock_input_stream(in);
9078 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9079 pthread_mutex_lock(&adev->lock);
9080 in->card_status = adev->card_status;
9081 pthread_mutex_unlock(&adev->lock);
9082 pthread_mutex_unlock(&in->lock);
9083
Aalique Grahame22e49102018-12-18 14:23:57 -08009084 stream_app_type_cfg_init(&in->app_type_cfg);
9085
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009086 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009087
9088 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9089 calloc(1, sizeof(streams_input_ctxt_t));
9090 if (in_ctxt == NULL) {
9091 ALOGE("%s fail to allocate input ctxt", __func__);
9092 ret = -ENOMEM;
9093 goto err_open;
9094 }
9095 in_ctxt->input = in;
9096
9097 pthread_mutex_lock(&adev->lock);
9098 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9099 pthread_mutex_unlock(&adev->lock);
9100
Eric Laurent994a6932013-07-17 11:51:42 -07009101 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009102 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009103
9104err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309105 if (in->usecase == USECASE_AUDIO_RECORD) {
9106 pthread_mutex_lock(&adev->lock);
9107 adev->pcm_record_uc_state = 0;
9108 pthread_mutex_unlock(&adev->lock);
9109 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009110 free(in);
9111 *stream_in = NULL;
9112 return ret;
9113}
9114
9115static void adev_close_input_stream(struct audio_hw_device *dev,
9116 struct audio_stream_in *stream)
9117{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009118 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009119 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009120 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309121
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309122 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009123
kunleiz70e57612018-12-28 17:50:23 +08009124 /* must deregister from sndmonitor first to prevent races
9125 * between the callback and close_stream
9126 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309127 audio_extn_snd_mon_unregister_listener(stream);
9128
kunleiz70e57612018-12-28 17:50:23 +08009129 /* Disable echo reference if there are no active input, hfp call
9130 * and sound trigger while closing input stream
9131 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009132 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009133 !audio_extn_hfp_is_active(adev) &&
9134 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08009135 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08009136 else
9137 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309138
Pallavid7c7a272018-01-16 11:22:55 +05309139 if (in == NULL) {
9140 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9141 return;
9142 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08009143 error_log_destroy(in->error_log);
9144 in->error_log = NULL;
9145
Pallavid7c7a272018-01-16 11:22:55 +05309146
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009147 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309148 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009149 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309150 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009151 if (ret != 0)
9152 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9153 __func__, ret);
9154 } else
9155 in_standby(&stream->common);
9156
Revathi Uddarajud2634032017-12-07 14:42:34 +05309157 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309158 if (in->usecase == USECASE_AUDIO_RECORD) {
9159 adev->pcm_record_uc_state = 0;
9160 }
9161
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009162 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009163 audio_extn_ssr_deinit();
9164 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009165
Garmond Leunge2433c32017-09-28 21:51:22 -07009166 if (audio_extn_ffv_get_stream() == in) {
9167 audio_extn_ffv_stream_deinit();
9168 }
9169
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309170 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009171 audio_extn_compr_cap_format_supported(in->config.format))
9172 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309173
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309174 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05309175 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009176
Mingming Yinfd7607b2016-01-22 12:48:44 -08009177 if (in->is_st_session) {
9178 ALOGV("%s: sound trigger pcm stop lab", __func__);
9179 audio_extn_sound_trigger_stop_lab(in);
9180 }
Derek Chenf939fb72018-11-13 13:34:41 -08009181 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9182 if (in_ctxt != NULL) {
9183 list_remove(&in_ctxt->list);
9184 free(in_ctxt);
9185 } else {
9186 ALOGW("%s, input stream already closed", __func__);
9187 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009188 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309189 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009190 return;
9191}
9192
Aalique Grahame22e49102018-12-18 14:23:57 -08009193/* verifies input and output devices and their capabilities.
9194 *
9195 * This verification is required when enabling extended bit-depth or
9196 * sampling rates, as not all qcom products support it.
9197 *
9198 * Suitable for calling only on initialization such as adev_open().
9199 * It fills the audio_device use_case_table[] array.
9200 *
9201 * Has a side-effect that it needs to configure audio routing / devices
9202 * in order to power up the devices and read the device parameters.
9203 * It does not acquire any hw device lock. Should restore the devices
9204 * back to "normal state" upon completion.
9205 */
9206static int adev_verify_devices(struct audio_device *adev)
9207{
9208 /* enumeration is a bit difficult because one really wants to pull
9209 * the use_case, device id, etc from the hidden pcm_device_table[].
9210 * In this case there are the following use cases and device ids.
9211 *
9212 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9213 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9214 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9215 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9216 * [USECASE_AUDIO_RECORD] = {0, 0},
9217 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9218 * [USECASE_VOICE_CALL] = {2, 2},
9219 *
9220 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9221 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9222 */
9223
9224 /* should be the usecases enabled in adev_open_input_stream() */
9225 static const int test_in_usecases[] = {
9226 USECASE_AUDIO_RECORD,
9227 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9228 };
9229 /* should be the usecases enabled in adev_open_output_stream()*/
9230 static const int test_out_usecases[] = {
9231 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9232 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9233 };
9234 static const usecase_type_t usecase_type_by_dir[] = {
9235 PCM_PLAYBACK,
9236 PCM_CAPTURE,
9237 };
9238 static const unsigned flags_by_dir[] = {
9239 PCM_OUT,
9240 PCM_IN,
9241 };
9242
9243 size_t i;
9244 unsigned dir;
9245 const unsigned card_id = adev->snd_card;
9246
9247 for (dir = 0; dir < 2; ++dir) {
9248 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9249 const unsigned flags_dir = flags_by_dir[dir];
9250 const size_t testsize =
9251 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9252 const int *testcases =
9253 dir ? test_in_usecases : test_out_usecases;
9254 const audio_devices_t audio_device =
9255 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9256
9257 for (i = 0; i < testsize; ++i) {
9258 const audio_usecase_t audio_usecase = testcases[i];
9259 int device_id;
9260 struct pcm_params **pparams;
9261 struct stream_out out;
9262 struct stream_in in;
9263 struct audio_usecase uc_info;
9264 int retval;
9265
9266 pparams = &adev->use_case_table[audio_usecase];
9267 pcm_params_free(*pparams); /* can accept null input */
9268 *pparams = NULL;
9269
9270 /* find the device ID for the use case (signed, for error) */
9271 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9272 if (device_id < 0)
9273 continue;
9274
9275 /* prepare structures for device probing */
9276 memset(&uc_info, 0, sizeof(uc_info));
9277 uc_info.id = audio_usecase;
9278 uc_info.type = usecase_type;
9279 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009280 memset(&in, 0, sizeof(in));
9281 in.device = audio_device;
9282 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9283 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009284 }
9285 memset(&out, 0, sizeof(out));
9286 out.devices = audio_device; /* only field needed in select_devices */
9287 uc_info.stream.out = &out;
9288 uc_info.devices = audio_device;
9289 uc_info.in_snd_device = SND_DEVICE_NONE;
9290 uc_info.out_snd_device = SND_DEVICE_NONE;
9291 list_add_tail(&adev->usecase_list, &uc_info.list);
9292
9293 /* select device - similar to start_(in/out)put_stream() */
9294 retval = select_devices(adev, audio_usecase);
9295 if (retval >= 0) {
9296 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9297#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009298 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009299 if (*pparams) {
9300 ALOGV("%s: (%s) card %d device %d", __func__,
9301 dir ? "input" : "output", card_id, device_id);
9302 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9303 } else {
9304 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9305 }
9306#endif
9307 }
9308
9309 /* deselect device - similar to stop_(in/out)put_stream() */
9310 /* 1. Get and set stream specific mixer controls */
9311 retval = disable_audio_route(adev, &uc_info);
9312 /* 2. Disable the rx device */
9313 retval = disable_snd_device(adev,
9314 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9315 list_remove(&uc_info.list);
9316 }
9317 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009318 return 0;
9319}
9320
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309321int adev_create_audio_patch(struct audio_hw_device *dev,
9322 unsigned int num_sources,
9323 const struct audio_port_config *sources,
9324 unsigned int num_sinks,
9325 const struct audio_port_config *sinks,
9326 audio_patch_handle_t *handle)
9327{
Derek Chenf939fb72018-11-13 13:34:41 -08009328 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309329
Derek Chenf939fb72018-11-13 13:34:41 -08009330 ret = audio_extn_hw_loopback_create_audio_patch(dev,
9331 num_sources,
9332 sources,
9333 num_sinks,
9334 sinks,
9335 handle);
9336 ret |= audio_extn_auto_hal_create_audio_patch(dev,
9337 num_sources,
9338 sources,
9339 num_sinks,
9340 sinks,
9341 handle);
9342 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309343}
9344
9345int adev_release_audio_patch(struct audio_hw_device *dev,
9346 audio_patch_handle_t handle)
9347{
Derek Chenf939fb72018-11-13 13:34:41 -08009348 int ret;
9349
9350 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
9351 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
9352 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309353}
9354
9355int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9356{
Derek Chenf13dd492018-11-13 14:53:51 -08009357 int ret = 0;
9358
9359 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9360 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9361 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309362}
9363
9364int adev_set_audio_port_config(struct audio_hw_device *dev,
9365 const struct audio_port_config *config)
9366{
Derek Chenf13dd492018-11-13 14:53:51 -08009367 int ret = 0;
9368
9369 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9370 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9371 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309372}
9373
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009374static int adev_dump(const audio_hw_device_t *device __unused,
9375 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009376{
9377 return 0;
9378}
9379
9380static int adev_close(hw_device_t *device)
9381{
Aalique Grahame22e49102018-12-18 14:23:57 -08009382 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309383 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009384
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309385 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009386 return 0;
9387
9388 pthread_mutex_lock(&adev_init_lock);
9389
9390 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309391 if (audio_extn_spkr_prot_is_enabled())
9392 audio_extn_spkr_prot_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309393 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009394 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009395 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009396 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009397 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309398 audio_extn_utils_release_streams_cfg_lists(
9399 &adev->streams_output_cfg_list,
9400 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309401 if (audio_extn_qap_is_enabled())
9402 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309403 if (audio_extn_qaf_is_enabled())
9404 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009405 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009406 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009407 free(adev->snd_dev_ref_cnt);
9408 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009409 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9410 pcm_params_free(adev->use_case_table[i]);
9411 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009412 if (adev->adm_deinit)
9413 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309414 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009415 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309416 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309417 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009418 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309419 if (adev->device_cfg_params) {
9420 free(adev->device_cfg_params);
9421 adev->device_cfg_params = NULL;
9422 }
Derek Chend2530072014-11-24 12:39:14 -08009423 if(adev->ext_hw_plugin)
9424 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009425 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009426 free(device);
9427 adev = NULL;
9428 }
9429 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309430 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009431 return 0;
9432}
9433
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009434/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9435 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9436 * just that it _might_ work.
9437 */
9438static int period_size_is_plausible_for_low_latency(int period_size)
9439{
9440 switch (period_size) {
9441 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009442 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009443 case 240:
9444 case 320:
9445 case 480:
9446 return 1;
9447 default:
9448 return 0;
9449 }
9450}
9451
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309452static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9453{
9454 bool is_snd_card_status = false;
9455 bool is_ext_device_status = false;
9456 char value[32];
9457 int card = -1;
9458 card_status_t status;
9459
9460 if (cookie != adev || !parms)
9461 return;
9462
9463 if (!parse_snd_card_status(parms, &card, &status)) {
9464 is_snd_card_status = true;
9465 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9466 is_ext_device_status = true;
9467 } else {
9468 // not a valid event
9469 return;
9470 }
9471
9472 pthread_mutex_lock(&adev->lock);
9473 if (card == adev->snd_card || is_ext_device_status) {
9474 if (is_snd_card_status && adev->card_status != status) {
9475 adev->card_status = status;
9476 platform_snd_card_update(adev->platform, status);
9477 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -08009478 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song5f7908f2019-07-02 00:32:23 +08009479 if (status == CARD_STATUS_OFFLINE)
9480 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309481 } else if (is_ext_device_status) {
9482 platform_set_parameters(adev->platform, parms);
9483 }
9484 }
9485 pthread_mutex_unlock(&adev->lock);
9486 return;
9487}
9488
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309489/* out and adev lock held */
9490static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9491{
9492 struct audio_usecase *uc_info;
9493 float left_p;
9494 float right_p;
9495 audio_devices_t devices;
9496
9497 uc_info = get_usecase_from_list(adev, out->usecase);
9498 if (uc_info == NULL) {
9499 ALOGE("%s: Could not find the usecase (%d) in the list",
9500 __func__, out->usecase);
9501 return -EINVAL;
9502 }
9503
9504 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9505 out->usecase, use_case_table[out->usecase]);
9506
9507 if (restore) {
9508 // restore A2DP device for active usecases and unmute if required
9509 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9510 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9511 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9512 select_devices(adev, uc_info->id);
9513 pthread_mutex_lock(&out->compr_mute_lock);
9514 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05309515 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309516 out->a2dp_compress_mute = false;
9517 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9518 }
9519 pthread_mutex_unlock(&out->compr_mute_lock);
9520 }
9521 } else {
Zhou Song28023002019-09-09 14:17:40 +08009522 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
9523 // mute compress stream if suspended
9524 pthread_mutex_lock(&out->compr_mute_lock);
9525 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309526 ALOGD("%s: selecting speaker and muting stream", __func__);
9527 devices = out->devices;
9528 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9529 left_p = out->volume_l;
9530 right_p = out->volume_r;
9531 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9532 compress_pause(out->compr);
9533 out_set_compr_volume(&out->stream, (float)0, (float)0);
9534 out->a2dp_compress_mute = true;
9535 select_devices(adev, out->usecase);
9536 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9537 compress_resume(out->compr);
9538 out->devices = devices;
9539 out->volume_l = left_p;
9540 out->volume_r = right_p;
9541 }
Zhou Song28023002019-09-09 14:17:40 +08009542 pthread_mutex_unlock(&out->compr_mute_lock);
9543 } else {
9544 // tear down a2dp path for non offloaded streams
9545 if (audio_extn_a2dp_source_is_suspended())
9546 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309547 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309548 }
9549 ALOGV("%s: exit", __func__);
9550 return 0;
9551}
9552
9553int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9554{
9555 int ret = 0;
9556
9557 lock_output_stream(out);
9558 pthread_mutex_lock(&adev->lock);
9559
9560 ret = check_a2dp_restore_l(adev, out, restore);
9561
9562 pthread_mutex_unlock(&adev->lock);
9563 pthread_mutex_unlock(&out->lock);
9564 return ret;
9565}
9566
Haynes Mathew George01156f92018-04-13 15:29:54 -07009567void adev_on_battery_status_changed(bool charging)
9568{
9569 pthread_mutex_lock(&adev->lock);
9570 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9571 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009572 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009573 pthread_mutex_unlock(&adev->lock);
9574}
9575
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009576static int adev_open(const hw_module_t *module, const char *name,
9577 hw_device_t **device)
9578{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309579 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009580 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309581 char mixer_ctl_name[128] = {0};
9582 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309583
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009584 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009585 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9586
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009587 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009588 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009589 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009590 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009591 ALOGD("%s: returning existing instance of adev", __func__);
9592 ALOGD("%s: exit", __func__);
9593 pthread_mutex_unlock(&adev_init_lock);
9594 return 0;
9595 }
9596
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009597 adev = calloc(1, sizeof(struct audio_device));
9598
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009599 if (!adev) {
9600 pthread_mutex_unlock(&adev_init_lock);
9601 return -ENOMEM;
9602 }
9603
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009604 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9605
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009606 // register audio ext hidl at the earliest
9607 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309608#ifdef DYNAMIC_LOG_ENABLED
9609 register_for_dynamic_logging("hal");
9610#endif
9611
Derek Chenf939fb72018-11-13 13:34:41 -08009612 /* default audio HAL major version */
9613 uint32_t maj_version = 2;
9614 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9615 maj_version = atoi(value);
9616
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009617 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009618 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009619 adev->device.common.module = (struct hw_module_t *)module;
9620 adev->device.common.close = adev_close;
9621
9622 adev->device.init_check = adev_init_check;
9623 adev->device.set_voice_volume = adev_set_voice_volume;
9624 adev->device.set_master_volume = adev_set_master_volume;
9625 adev->device.get_master_volume = adev_get_master_volume;
9626 adev->device.set_master_mute = adev_set_master_mute;
9627 adev->device.get_master_mute = adev_get_master_mute;
9628 adev->device.set_mode = adev_set_mode;
9629 adev->device.set_mic_mute = adev_set_mic_mute;
9630 adev->device.get_mic_mute = adev_get_mic_mute;
9631 adev->device.set_parameters = adev_set_parameters;
9632 adev->device.get_parameters = adev_get_parameters;
9633 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9634 adev->device.open_output_stream = adev_open_output_stream;
9635 adev->device.close_output_stream = adev_close_output_stream;
9636 adev->device.open_input_stream = adev_open_input_stream;
9637 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309638 adev->device.create_audio_patch = adev_create_audio_patch;
9639 adev->device.release_audio_patch = adev_release_audio_patch;
9640 adev->device.get_audio_port = adev_get_audio_port;
9641 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009642 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309643 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009644
9645 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009646 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009647 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009648 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009649 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009650 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009651 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309652 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009653 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009654 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009655 /* Init audio and voice feature */
9656 audio_extn_feature_init();
9657 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009658 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009659 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009660 list_init(&adev->active_inputs_list);
9661 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +05309662 list_init(&adev->audio_patch_record_list);
9663 adev->audio_patch_index = 0;
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009664 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009665 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309666 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309667 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309668 adev->perf_lock_opts[0] = 0x101;
9669 adev->perf_lock_opts[1] = 0x20E;
9670 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009671 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009672 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309673 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009674 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009676 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009677 adev->platform = platform_init(adev);
9678 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009679 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009680 free(adev->snd_dev_ref_cnt);
9681 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009682 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009683 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9684 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009685 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009686 return -EINVAL;
9687 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009688
Aalique Grahame22e49102018-12-18 14:23:57 -08009689 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309690 if (audio_extn_qap_is_enabled()) {
9691 ret = audio_extn_qap_init(adev);
9692 if (ret < 0) {
9693 pthread_mutex_destroy(&adev->lock);
9694 free(adev);
9695 adev = NULL;
9696 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9697 *device = NULL;
9698 pthread_mutex_unlock(&adev_init_lock);
9699 return ret;
9700 }
9701 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
9702 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
9703 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009704
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309705 if (audio_extn_qaf_is_enabled()) {
9706 ret = audio_extn_qaf_init(adev);
9707 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009708 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309709 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009710 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309711 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9712 *device = NULL;
9713 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309714 return ret;
9715 }
9716
9717 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9718 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9719 }
9720
Derek Chenae7b0342019-02-08 15:17:04 -08009721 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009722 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9723
Eric Laurentc4aef752013-09-12 17:45:53 -07009724 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9725 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9726 if (adev->visualizer_lib == NULL) {
9727 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9728 } else {
9729 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9730 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009731 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009732 "visualizer_hal_start_output");
9733 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009734 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009735 "visualizer_hal_stop_output");
9736 }
9737 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309738 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009739 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009740 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009741 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309742 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009743 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009744
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009745 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9746 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9747 if (adev->offload_effects_lib == NULL) {
9748 ALOGE("%s: DLOPEN failed for %s", __func__,
9749 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9750 } else {
9751 ALOGV("%s: DLOPEN successful for %s", __func__,
9752 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9753 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309754 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009755 "offload_effects_bundle_hal_start_output");
9756 adev->offload_effects_stop_output =
9757 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9758 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009759 adev->offload_effects_set_hpx_state =
9760 (int (*)(bool))dlsym(adev->offload_effects_lib,
9761 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309762 adev->offload_effects_get_parameters =
9763 (void (*)(struct str_parms *, struct str_parms *))
9764 dlsym(adev->offload_effects_lib,
9765 "offload_effects_bundle_get_parameters");
9766 adev->offload_effects_set_parameters =
9767 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9768 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009769 }
9770 }
9771
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009772 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9773 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9774 if (adev->adm_lib == NULL) {
9775 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9776 } else {
9777 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9778 adev->adm_init = (adm_init_t)
9779 dlsym(adev->adm_lib, "adm_init");
9780 adev->adm_deinit = (adm_deinit_t)
9781 dlsym(adev->adm_lib, "adm_deinit");
9782 adev->adm_register_input_stream = (adm_register_input_stream_t)
9783 dlsym(adev->adm_lib, "adm_register_input_stream");
9784 adev->adm_register_output_stream = (adm_register_output_stream_t)
9785 dlsym(adev->adm_lib, "adm_register_output_stream");
9786 adev->adm_deregister_stream = (adm_deregister_stream_t)
9787 dlsym(adev->adm_lib, "adm_deregister_stream");
9788 adev->adm_request_focus = (adm_request_focus_t)
9789 dlsym(adev->adm_lib, "adm_request_focus");
9790 adev->adm_abandon_focus = (adm_abandon_focus_t)
9791 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009792 adev->adm_set_config = (adm_set_config_t)
9793 dlsym(adev->adm_lib, "adm_set_config");
9794 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9795 dlsym(adev->adm_lib, "adm_request_focus_v2");
9796 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9797 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9798 adev->adm_on_routing_change = (adm_on_routing_change_t)
9799 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009800 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9801 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009802 }
9803 }
9804
Aalique Grahame22e49102018-12-18 14:23:57 -08009805 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009806 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009807 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009808 //initialize this to false for now,
9809 //this will be set to true through set param
9810 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009811
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009812 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009813 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009814
9815 if (k_enable_extended_precision)
9816 adev_verify_devices(adev);
9817
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009818 adev->dsp_bit_width_enforce_mode =
9819 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009820
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309821 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9822 &adev->streams_output_cfg_list,
9823 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009824
Kiran Kandi910e1862013-10-29 13:29:42 -07009825 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009826
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009827 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009828 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9829 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009830 trial = atoi(value);
9831 if (period_size_is_plausible_for_low_latency(trial)) {
9832 pcm_config_low_latency.period_size = trial;
9833 pcm_config_low_latency.start_threshold = trial / 4;
9834 pcm_config_low_latency.avail_min = trial / 4;
9835 configured_low_latency_capture_period_size = trial;
9836 }
9837 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009838 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9839 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009840 trial = atoi(value);
9841 if (period_size_is_plausible_for_low_latency(trial)) {
9842 configured_low_latency_capture_period_size = trial;
9843 }
9844 }
9845
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009846 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9847
Eric Laurent4b084132018-10-19 17:33:43 -07009848 adev->camera_orientation = CAMERA_DEFAULT;
9849
Aalique Grahame22e49102018-12-18 14:23:57 -08009850 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9851 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009852 af_period_multiplier = atoi(value);
9853 if (af_period_multiplier < 0)
9854 af_period_multiplier = 2;
9855 else if (af_period_multiplier > 4)
9856 af_period_multiplier = 4;
9857
9858 ALOGV("new period_multiplier = %d", af_period_multiplier);
9859 }
9860
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009861 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009862
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009863 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009864 pthread_mutex_unlock(&adev_init_lock);
9865
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009866 if (adev->adm_init)
9867 adev->adm_data = adev->adm_init();
9868
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309869 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309870 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009871 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309872
9873 audio_extn_snd_mon_init();
9874 pthread_mutex_lock(&adev->lock);
9875 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9876 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009877 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9878 /*
9879 * if the battery state callback happens before charging can be queried,
9880 * it will be guarded with the adev->lock held in the cb function and so
9881 * the callback value will reflect the latest state
9882 */
9883 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309884 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009885 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009886 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009887 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309888 /* Allocate memory for Device config params */
9889 adev->device_cfg_params = (struct audio_device_config_param*)
9890 calloc(platform_get_max_codec_backend(),
9891 sizeof(struct audio_device_config_param));
9892 if (adev->device_cfg_params == NULL)
9893 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309894
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309895 /*
9896 * Check if new PSPD matrix mixer control is supported. If not
9897 * supported, then set flag so that old mixer ctrl is sent while
9898 * sending pspd coefficients on older kernel version. Query mixer
9899 * control for default pcm id and channel value one.
9900 */
9901 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9902 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9903
9904 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9905 if (!ctl) {
9906 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9907 __func__, mixer_ctl_name);
9908 adev->use_old_pspd_mix_ctrl = true;
9909 }
9910
Eric Laurent994a6932013-07-17 11:51:42 -07009911 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009912 return 0;
9913}
9914
9915static struct hw_module_methods_t hal_module_methods = {
9916 .open = adev_open,
9917};
9918
9919struct audio_module HAL_MODULE_INFO_SYM = {
9920 .common = {
9921 .tag = HARDWARE_MODULE_TAG,
9922 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9923 .hal_api_version = HARDWARE_HAL_API_VERSION,
9924 .id = AUDIO_HARDWARE_MODULE_ID,
9925 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009926 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009927 .methods = &hal_module_methods,
9928 },
9929};