blob: 954191e0ba1300103ee6f7766644ad3e6355dd66 [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),
Mingshu pang9915e022019-10-25 15:38:27 +0800490 STRING_TO_ENUM(352800),
491 STRING_TO_ENUM(384000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700492};
493
Carter Hsu2e429db2019-05-14 18:50:52 +0800494struct in_effect_list {
495 struct listnode list;
496 effect_handle_t handle;
497};
498
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700499static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700500static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700501static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700502//cache last MBDRC cal step level
503static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700504
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530505static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
506static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700507static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800508static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530509static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530510
Derek Chen6f293672019-04-01 01:40:24 -0700511static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
512static void in_snd_mon_cb(void * stream, struct str_parms * parms);
513static void out_snd_mon_cb(void * stream, struct str_parms * parms);
514
Zhou Song4721e282019-08-26 14:16:12 +0800515static int configure_btsco_sample_rate(snd_device_t snd_device);
516
Vatsal Buchac09ae062018-11-14 13:25:08 +0530517#ifdef AUDIO_FEATURE_ENABLED_GCOV
518extern void __gcov_flush();
519static void enable_gcov()
520{
521 __gcov_flush();
522}
523#else
524static void enable_gcov()
525{
526}
527#endif
528
justinweng20fb6d82019-02-21 18:49:00 -0700529static int in_set_microphone_direction(const struct audio_stream_in *stream,
530 audio_microphone_direction_t dir);
531static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
532
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700533static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
534 int flags __unused)
535{
536 int dir = 0;
537 switch (uc_id) {
538 case USECASE_AUDIO_RECORD_LOW_LATENCY:
539 dir = 1;
540 case USECASE_AUDIO_PLAYBACK_ULL:
541 break;
542 default:
543 return false;
544 }
545
546 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
547 PCM_PLAYBACK : PCM_CAPTURE);
548 if (adev->adm_is_noirq_avail)
549 return adev->adm_is_noirq_avail(adev->adm_data,
550 adev->snd_card, dev_id, dir);
551 return false;
552}
553
554static void register_out_stream(struct stream_out *out)
555{
556 struct audio_device *adev = out->dev;
557 if (is_offload_usecase(out->usecase) ||
558 !adev->adm_register_output_stream)
559 return;
560
561 // register stream first for backward compatibility
562 adev->adm_register_output_stream(adev->adm_data,
563 out->handle,
564 out->flags);
565
566 if (!adev->adm_set_config)
567 return;
568
569 if (out->realtime)
570 adev->adm_set_config(adev->adm_data,
571 out->handle,
572 out->pcm, &out->config);
573}
574
575static void register_in_stream(struct stream_in *in)
576{
577 struct audio_device *adev = in->dev;
578 if (!adev->adm_register_input_stream)
579 return;
580
581 adev->adm_register_input_stream(adev->adm_data,
582 in->capture_handle,
583 in->flags);
584
585 if (!adev->adm_set_config)
586 return;
587
588 if (in->realtime)
589 adev->adm_set_config(adev->adm_data,
590 in->capture_handle,
591 in->pcm,
592 &in->config);
593}
594
595static void request_out_focus(struct stream_out *out, long ns)
596{
597 struct audio_device *adev = out->dev;
598
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700599 if (adev->adm_request_focus_v2)
600 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
601 else if (adev->adm_request_focus)
602 adev->adm_request_focus(adev->adm_data, out->handle);
603}
604
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700605static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700606{
607 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700608 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700609
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700610 if (adev->adm_request_focus_v2_1)
611 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
612 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700613 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
614 else if (adev->adm_request_focus)
615 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700616
617 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700618}
619
620static void release_out_focus(struct stream_out *out)
621{
622 struct audio_device *adev = out->dev;
623
624 if (adev->adm_abandon_focus)
625 adev->adm_abandon_focus(adev->adm_data, out->handle);
626}
627
628static void release_in_focus(struct stream_in *in)
629{
630 struct audio_device *adev = in->dev;
631 if (adev->adm_abandon_focus)
632 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
633}
634
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530635static int parse_snd_card_status(struct str_parms *parms, int *card,
636 card_status_t *status)
637{
638 char value[32]={0};
639 char state[32]={0};
640
641 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
642 if (ret < 0)
643 return -1;
644
645 // sscanf should be okay as value is of max length 32.
646 // same as sizeof state.
647 if (sscanf(value, "%d,%s", card, state) < 2)
648 return -1;
649
650 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
651 CARD_STATUS_OFFLINE;
652 return 0;
653}
654
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700655static inline void adjust_frames_for_device_delay(struct stream_out *out,
656 uint32_t *dsp_frames) {
657 // Adjustment accounts for A2dp encoder latency with offload usecases
658 // Note: Encoder latency is returned in ms.
659 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
660 unsigned long offset =
661 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
662 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
663 }
664}
665
vivek mehtaa76401a2015-04-24 14:12:15 -0700666__attribute__ ((visibility ("default")))
667bool audio_hw_send_gain_dep_calibration(int level) {
668 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700669 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700670
671 pthread_mutex_lock(&adev_init_lock);
672
673 if (adev != NULL && adev->platform != NULL) {
674 pthread_mutex_lock(&adev->lock);
675 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700676
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530677 // cache level info for any of the use case which
678 // was not started.
679 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700680
vivek mehtaa76401a2015-04-24 14:12:15 -0700681 pthread_mutex_unlock(&adev->lock);
682 } else {
683 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
684 }
685
686 pthread_mutex_unlock(&adev_init_lock);
687
688 return ret_val;
689}
690
Ashish Jain5106d362016-05-11 19:23:33 +0530691static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
692{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800693 bool gapless_enabled = false;
694 const char *mixer_ctl_name = "Compress Gapless Playback";
695 struct mixer_ctl *ctl;
696
697 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700698 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530699
700 /*Disable gapless if its AV playback*/
701 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800702
703 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
704 if (!ctl) {
705 ALOGE("%s: Could not get ctl for mixer cmd - %s",
706 __func__, mixer_ctl_name);
707 return -EINVAL;
708 }
709
710 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
711 ALOGE("%s: Could not set gapless mode %d",
712 __func__, gapless_enabled);
713 return -EINVAL;
714 }
715 return 0;
716}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700717
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700718__attribute__ ((visibility ("default")))
719int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
720 int table_size) {
721 int ret_val = 0;
722 ALOGV("%s: enter ... ", __func__);
723
724 pthread_mutex_lock(&adev_init_lock);
725 if (adev == NULL) {
726 ALOGW("%s: adev is NULL .... ", __func__);
727 goto done;
728 }
729
730 pthread_mutex_lock(&adev->lock);
731 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
732 pthread_mutex_unlock(&adev->lock);
733done:
734 pthread_mutex_unlock(&adev_init_lock);
735 ALOGV("%s: exit ... ", __func__);
736 return ret_val;
737}
738
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800739bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800740{
741 bool ret = false;
742 ALOGV("%s: enter ...", __func__);
743
744 pthread_mutex_lock(&adev_init_lock);
745
746 if (adev != NULL && adev->platform != NULL) {
747 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800748 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800749 pthread_mutex_unlock(&adev->lock);
750 }
751
752 pthread_mutex_unlock(&adev_init_lock);
753
754 ALOGV("%s: exit with ret %d", __func__, ret);
755 return ret;
756}
Aalique Grahame22e49102018-12-18 14:23:57 -0800757
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700758static bool is_supported_format(audio_format_t format)
759{
Eric Laurent86e17132013-09-12 17:49:30 -0700760 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530761 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530762 format == AUDIO_FORMAT_AAC_LC ||
763 format == AUDIO_FORMAT_AAC_HE_V1 ||
764 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530765 format == AUDIO_FORMAT_AAC_ADTS_LC ||
766 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
767 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530768 format == AUDIO_FORMAT_AAC_LATM_LC ||
769 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
770 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530771 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
772 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530773 format == AUDIO_FORMAT_PCM_FLOAT ||
774 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700775 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530776 format == AUDIO_FORMAT_AC3 ||
777 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700778 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530779 format == AUDIO_FORMAT_DTS ||
780 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800781 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530782 format == AUDIO_FORMAT_ALAC ||
783 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530784 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530785 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800786 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530787 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700788 format == AUDIO_FORMAT_APTX ||
789 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800790 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700791
792 return false;
793}
794
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700795static inline bool is_mmap_usecase(audio_usecase_t uc_id)
796{
797 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
798 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
799}
800
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700801static inline bool is_valid_volume(float left, float right)
802{
803 return ((left >= 0.0f && right >= 0.0f) ? true : false);
804}
805
Avinash Vaish71a8b972014-07-24 15:36:33 +0530806static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
807 struct audio_usecase *uc_info)
808{
809 struct listnode *node;
810 struct audio_usecase *usecase;
811
812 if (uc_info == NULL)
813 return -EINVAL;
814
815 /* Re-route all voice usecases on the shared backend other than the
816 specified usecase to new snd devices */
817 list_for_each(node, &adev->usecase_list) {
818 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800819 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530820 enable_audio_route(adev, usecase);
821 }
822 return 0;
823}
824
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530825static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530826{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530827 ALOGV("%s", __func__);
828 audio_route_apply_and_update_path(adev->audio_route,
829 "asrc-mode");
830 adev->asrc_mode_enabled = true;
831}
832
833static void disable_asrc_mode(struct audio_device *adev)
834{
835 ALOGV("%s", __func__);
836 audio_route_reset_and_update_path(adev->audio_route,
837 "asrc-mode");
838 adev->asrc_mode_enabled = false;
839}
840
841/*
842 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
843 * 44.1 or Native DSD backends are enabled for any of current use case.
844 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
845 * - Disable current mix path use case(Headphone backend) and re-enable it with
846 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
847 * e.g. Naitve DSD or Headphone 44.1 -> + 48
848 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530849static void check_and_set_asrc_mode(struct audio_device *adev,
850 struct audio_usecase *uc_info,
851 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530852{
853 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530854 int i, num_new_devices = 0;
855 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
856 /*
857 *Split snd device for new combo use case
858 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
859 */
860 if (platform_split_snd_device(adev->platform,
861 snd_device,
862 &num_new_devices,
863 split_new_snd_devices) == 0) {
864 for (i = 0; i < num_new_devices; i++)
865 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
866 } else {
867 int new_backend_idx = platform_get_backend_index(snd_device);
868 if (((new_backend_idx == HEADPHONE_BACKEND) ||
869 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
870 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
871 !adev->asrc_mode_enabled) {
872 struct listnode *node = NULL;
873 struct audio_usecase *uc = NULL;
874 struct stream_out *curr_out = NULL;
875 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
876 int i, num_devices, ret = 0;
877 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530878
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530879 list_for_each(node, &adev->usecase_list) {
880 uc = node_to_item(node, struct audio_usecase, list);
881 curr_out = (struct stream_out*) uc->stream.out;
882 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
883 /*
884 *Split snd device for existing combo use case
885 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
886 */
887 ret = platform_split_snd_device(adev->platform,
888 uc->out_snd_device,
889 &num_devices,
890 split_snd_devices);
891 if (ret < 0 || num_devices == 0) {
892 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
893 split_snd_devices[0] = uc->out_snd_device;
894 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800895 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530896 for (i = 0; i < num_devices; i++) {
897 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
898 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
899 if((new_backend_idx == HEADPHONE_BACKEND) &&
900 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
901 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
902 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
903 __func__);
904 enable_asrc_mode(adev);
905 break;
906 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
907 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
908 (usecase_backend_idx == HEADPHONE_BACKEND)) {
909 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
910 __func__);
911 disable_audio_route(adev, uc);
912 disable_snd_device(adev, uc->out_snd_device);
913 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
914 if (new_backend_idx == DSD_NATIVE_BACKEND)
915 audio_route_apply_and_update_path(adev->audio_route,
916 "hph-true-highquality-mode");
917 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
918 (curr_out->bit_width >= 24))
919 audio_route_apply_and_update_path(adev->audio_route,
920 "hph-highquality-mode");
921 enable_asrc_mode(adev);
922 enable_snd_device(adev, uc->out_snd_device);
923 enable_audio_route(adev, uc);
924 break;
925 }
926 }
927 // reset split devices count
928 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800929 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530930 if (adev->asrc_mode_enabled)
931 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530932 }
933 }
934 }
935}
936
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700937static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
938 struct audio_effect_config effect_config,
939 unsigned int param_value)
940{
941 char mixer_ctl_name[] = "Audio Effect";
942 struct mixer_ctl *ctl;
943 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800944 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700945
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700946 if (in == NULL) {
947 ALOGE("%s: active input stream is NULL", __func__);
948 return -EINVAL;
949 }
950
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700951 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
952 if (!ctl) {
953 ALOGE("%s: Could not get mixer ctl - %s",
954 __func__, mixer_ctl_name);
955 return -EINVAL;
956 }
957
958 set_values[0] = 1; //0:Rx 1:Tx
959 set_values[1] = in->app_type_cfg.app_type;
960 set_values[2] = (long)effect_config.module_id;
961 set_values[3] = (long)effect_config.instance_id;
962 set_values[4] = (long)effect_config.param_id;
963 set_values[5] = param_value;
964
965 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
966
967 return 0;
968
969}
970
971static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
972 int effect_type, unsigned int *param_value)
973{
974 int ret = 0;
975 struct audio_effect_config other_effect_config;
976 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800977 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700978
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700979 if (in == NULL) {
980 ALOGE("%s: active input stream is NULL", __func__);
981 return -EINVAL;
982 }
983
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700984 usecase = get_usecase_from_list(adev, in->usecase);
985 if (!usecase)
986 return -EINVAL;
987
988 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
989 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
990 if (ret < 0) {
991 ALOGE("%s Failed to get effect params %d", __func__, ret);
992 return ret;
993 }
994
995 if (module_id == other_effect_config.module_id) {
996 //Same module id for AEC/NS. Values need to be combined
997 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
998 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
999 *param_value |= other_effect_config.param_value;
1000 }
1001 }
1002
1003 return ret;
1004}
1005
1006static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301007{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001008 struct audio_effect_config effect_config;
1009 struct audio_usecase *usecase = NULL;
1010 int ret = 0;
1011 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001012 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001013
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001014 if(!voice_extn_is_dynamic_ecns_enabled())
1015 return ENOSYS;
1016
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001017 if (!in) {
1018 ALOGE("%s: Invalid input stream", __func__);
1019 return -EINVAL;
1020 }
1021
1022 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1023
1024 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001025 if (usecase == NULL) {
1026 ALOGE("%s: Could not find the usecase (%d) in the list",
1027 __func__, in->usecase);
1028 return -EINVAL;
1029 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001030
1031 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1032 if (ret < 0) {
1033 ALOGE("%s Failed to get module id %d", __func__, ret);
1034 return ret;
1035 }
1036 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1037 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1038
1039 if(enable)
1040 param_value = effect_config.param_value;
1041
1042 /*Special handling for AEC & NS effects Param values need to be
1043 updated if module ids are same*/
1044
1045 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1046 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1047 if (ret < 0)
1048 return ret;
1049 }
1050
1051 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1052
1053 return ret;
1054}
1055
1056static void check_and_enable_effect(struct audio_device *adev)
1057{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001058 if(!voice_extn_is_dynamic_ecns_enabled())
1059 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001060
Eric Laurent637e2d42018-11-15 12:24:31 -08001061 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001062
Eric Laurent637e2d42018-11-15 12:24:31 -08001063 if (in != NULL && !in->standby) {
1064 if (in->enable_aec)
1065 enable_disable_effect(adev, EFFECT_AEC, true);
1066
1067 if (in->enable_ns &&
1068 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1069 enable_disable_effect(adev, EFFECT_NS, true);
1070 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001071 }
1072}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001073
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001074int pcm_ioctl(struct pcm *pcm, int request, ...)
1075{
1076 va_list ap;
1077 void * arg;
1078 int pcm_fd = *(int*)pcm;
1079
1080 va_start(ap, request);
1081 arg = va_arg(ap, void *);
1082 va_end(ap);
1083
1084 return ioctl(pcm_fd, request, arg);
1085}
1086
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001087int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001088 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001089{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001090 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001091 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301092 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301093 struct stream_in *in = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301094 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001095
1096 if (usecase == NULL)
1097 return -EINVAL;
1098
1099 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1100
Carter Hsu2e429db2019-05-14 18:50:52 +08001101 if (usecase->type == PCM_CAPTURE) {
1102 struct stream_in *in = usecase->stream.in;
1103 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001104 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001105
1106 if (in) {
1107 if (in->enable_aec || in->enable_ec_port) {
1108 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
1109 struct listnode *node;
1110 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1111 USECASE_AUDIO_PLAYBACK_VOIP);
1112 if (voip_usecase) {
1113 out_device = voip_usecase->stream.out->devices;
1114 } else if (adev->primary_output &&
1115 !adev->primary_output->standby) {
1116 out_device = adev->primary_output->devices;
1117 } else {
1118 list_for_each(node, &adev->usecase_list) {
1119 uinfo = node_to_item(node, struct audio_usecase, list);
1120 if (uinfo->type != PCM_CAPTURE) {
1121 out_device = uinfo->stream.out->devices;
1122 break;
1123 }
1124 }
1125 }
1126 platform_set_echo_reference(adev, true, out_device);
1127 in->ec_opened = true;
1128 }
1129 }
1130 } else if (usecase->type == TRANSCODE_LOOPBACK_TX) {
1131 snd_device = usecase->in_snd_device;
1132 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001133 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001134 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001135
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001136#ifdef DS1_DOLBY_DAP_ENABLED
1137 audio_extn_dolby_set_dmid(adev);
1138 audio_extn_dolby_set_endpoint(adev);
1139#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001140 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001141 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301142 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001143 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001144 if (audio_extn_is_maxx_audio_enabled())
1145 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301146 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301147 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1148 out = usecase->stream.out;
1149 if (out && out->compr)
1150 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1151 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301152
1153 if (usecase->type == PCM_CAPTURE) {
1154 in = usecase->stream.in;
1155 if (in && is_loopback_input_device(in->device)) {
1156 ALOGD("%s: set custom mtmx params v1", __func__);
1157 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1158 }
1159 } else {
1160 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1161 }
Manish Dewangan58229382017-02-02 15:48:41 +05301162
Andy Hung756ecc12018-10-19 17:47:12 -07001163 // we shouldn't truncate mixer_path
1164 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1165 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1166 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001167 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001168 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301169 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1170 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1171 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1172 if (parms) {
1173 audio_extn_fm_set_parameters(adev, parms);
1174 str_parms_destroy(parms);
1175 }
1176 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001177 ALOGV("%s: exit", __func__);
1178 return 0;
1179}
1180
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001181int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001182 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001183{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001184 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001185 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301186 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001187
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301188 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001189 return -EINVAL;
1190
1191 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301192 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001193 snd_device = usecase->in_snd_device;
1194 else
1195 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001196 // we shouldn't truncate mixer_path
1197 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1198 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1199 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001200 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001201 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001202 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001203 if (usecase->type == PCM_CAPTURE) {
1204 struct stream_in *in = usecase->stream.in;
1205 if (in && in->ec_opened) {
1206 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
1207 in->ec_opened = false;
1208 }
1209 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001210 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301211 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301212
1213 if (usecase->type == PCM_CAPTURE) {
1214 in = usecase->stream.in;
1215 if (in && is_loopback_input_device(in->device)) {
1216 ALOGD("%s: reset custom mtmx params v1", __func__);
1217 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1218 }
1219 } else {
1220 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1221 }
1222
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001223 if ((usecase->type == PCM_PLAYBACK) &&
1224 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301225 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001227 ALOGV("%s: exit", __func__);
1228 return 0;
1229}
1230
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001231int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001232 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001233{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301234 int i, num_devices = 0;
1235 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001236 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1237
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001238 if (snd_device < SND_DEVICE_MIN ||
1239 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001240 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001241 return -EINVAL;
1242 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001243
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001244 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001245 ALOGE("%s: Invalid sound device returned", __func__);
1246 return -EINVAL;
1247 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001248
1249 adev->snd_dev_ref_cnt[snd_device]++;
1250
1251 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1252 (platform_split_snd_device(adev->platform,
1253 snd_device,
1254 &num_devices,
1255 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001256 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001257 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001258 return 0;
1259 }
1260
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001261 if (audio_extn_spkr_prot_is_enabled())
1262 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001263
Aalique Grahame22e49102018-12-18 14:23:57 -08001264 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1265
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001266 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1267 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001268 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1269 goto err;
1270 }
1271 audio_extn_dev_arbi_acquire(snd_device);
1272 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001273 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001274 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001275 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001276 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001277 } else if (platform_split_snd_device(adev->platform,
1278 snd_device,
1279 &num_devices,
1280 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301281 for (i = 0; i < num_devices; i++) {
1282 enable_snd_device(adev, new_snd_devices[i]);
1283 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001284 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001285 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001286 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301287
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301288
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001289 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1290 (audio_extn_a2dp_start_playback() < 0)) {
1291 ALOGE(" fail to configure A2dp Source control path ");
1292 goto err;
1293 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001294
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001295 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1296 (audio_extn_a2dp_start_capture() < 0)) {
1297 ALOGE(" fail to configure A2dp Sink control path ");
1298 goto err;
1299 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301300
Zhou Song12c29502019-03-16 10:37:18 +08001301 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1302 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1303 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1304 (audio_extn_sco_start_configuration() < 0)) {
1305 ALOGE(" fail to configure sco control path ");
1306 goto err;
1307 }
1308
Zhou Song4721e282019-08-26 14:16:12 +08001309 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001310 /* due to the possibility of calibration overwrite between listen
1311 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001312 audio_extn_sound_trigger_update_device_status(snd_device,
1313 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301314 audio_extn_listen_update_device_status(snd_device,
1315 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001316 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001317 audio_extn_sound_trigger_update_device_status(snd_device,
1318 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301319 audio_extn_listen_update_device_status(snd_device,
1320 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001321 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001322 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001323 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001324 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301325
1326 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1327 !adev->native_playback_enabled &&
1328 audio_is_true_native_stream_active(adev)) {
1329 ALOGD("%s: %d: napb: enabling native mode in hardware",
1330 __func__, __LINE__);
1331 audio_route_apply_and_update_path(adev->audio_route,
1332 "true-native-mode");
1333 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301334 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301335 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1336 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001337 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001338 ALOGD("%s: init ec ref loopback", __func__);
1339 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1340 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001341 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001342 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001343err:
1344 adev->snd_dev_ref_cnt[snd_device]--;
1345 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001346}
1347
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001348int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001349 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001350{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301351 int i, num_devices = 0;
1352 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001353 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1354
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001355 if (snd_device < SND_DEVICE_MIN ||
1356 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001357 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001358 return -EINVAL;
1359 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001360
1361 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1362 ALOGE("%s: Invalid sound device returned", __func__);
1363 return -EINVAL;
1364 }
1365
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001366 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1367 ALOGE("%s: device ref cnt is already 0", __func__);
1368 return -EINVAL;
1369 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001370
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001371 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001372
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001373
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001374 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001375 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301376
Aalique Grahame22e49102018-12-18 14:23:57 -08001377 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1378
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001379 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1380 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001381 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001382
1383 // when speaker device is disabled, reset swap.
1384 // will be renabled on usecase start
1385 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001386 } else if (platform_split_snd_device(adev->platform,
1387 snd_device,
1388 &num_devices,
1389 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301390 for (i = 0; i < num_devices; i++) {
1391 disable_snd_device(adev, new_snd_devices[i]);
1392 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001393 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001394 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001395 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001396 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001397
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001398 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301399 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001400 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001401 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001402 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001403 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301404 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001405 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301406 adev->native_playback_enabled) {
1407 ALOGD("%s: %d: napb: disabling native mode in hardware",
1408 __func__, __LINE__);
1409 audio_route_reset_and_update_path(adev->audio_route,
1410 "true-native-mode");
1411 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001412 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301413 adev->asrc_mode_enabled) {
1414 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301415 disable_asrc_mode(adev);
1416 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001417 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301418 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001419 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001420 ALOGD("%s: deinit ec ref loopback", __func__);
1421 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1422 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001423
1424 audio_extn_utils_release_snd_device(snd_device);
1425 } else {
1426 if (platform_split_snd_device(adev->platform,
1427 snd_device,
1428 &num_devices,
1429 new_snd_devices) == 0) {
1430 for (i = 0; i < num_devices; i++) {
1431 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1432 }
1433 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001434 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001436 return 0;
1437}
1438
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001439/*
1440 legend:
1441 uc - existing usecase
1442 new_uc - new usecase
1443 d1, d11, d2 - SND_DEVICE enums
1444 a1, a2 - corresponding ANDROID device enums
1445 B1, B2 - backend strings
1446
1447case 1
1448 uc->dev d1 (a1) B1
1449 new_uc->dev d1 (a1), d2 (a2) B1, B2
1450
1451 resolution: disable and enable uc->dev on d1
1452
1453case 2
1454 uc->dev d1 (a1) B1
1455 new_uc->dev d11 (a1) B1
1456
1457 resolution: need to switch uc since d1 and d11 are related
1458 (e.g. speaker and voice-speaker)
1459 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1460
1461case 3
1462 uc->dev d1 (a1) B1
1463 new_uc->dev d2 (a2) B2
1464
1465 resolution: no need to switch uc
1466
1467case 4
1468 uc->dev d1 (a1) B1
1469 new_uc->dev d2 (a2) B1
1470
1471 resolution: disable enable uc-dev on d2 since backends match
1472 we cannot enable two streams on two different devices if they
1473 share the same backend. e.g. if offload is on speaker device using
1474 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1475 using the same backend, offload must also be switched to voice-handset.
1476
1477case 5
1478 uc->dev d1 (a1) B1
1479 new_uc->dev d1 (a1), d2 (a2) B1
1480
1481 resolution: disable enable uc-dev on d2 since backends match
1482 we cannot enable two streams on two different devices if they
1483 share the same backend.
1484
1485case 6
1486 uc->dev d1 (a1) B1
1487 new_uc->dev d2 (a1) B2
1488
1489 resolution: no need to switch
1490
1491case 7
1492 uc->dev d1 (a1), d2 (a2) B1, B2
1493 new_uc->dev d1 (a1) B1
1494
1495 resolution: no need to switch
1496
Zhou Song4ba65882018-07-09 14:48:07 +08001497case 8
1498 uc->dev d1 (a1) B1
1499 new_uc->dev d11 (a1), d2 (a2) B1, B2
1500 resolution: compared to case 1, for this case, d1 and d11 are related
1501 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001502*/
1503static snd_device_t derive_playback_snd_device(void * platform,
1504 struct audio_usecase *uc,
1505 struct audio_usecase *new_uc,
1506 snd_device_t new_snd_device)
1507{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301508 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001509
1510 snd_device_t d1 = uc->out_snd_device;
1511 snd_device_t d2 = new_snd_device;
1512
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301513 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301514 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301515 a1 = uc->stream.inout->out_config.devices;
1516 a2 = new_uc->stream.inout->out_config.devices;
1517 break;
1518 default :
1519 a1 = uc->stream.out->devices;
1520 a2 = new_uc->stream.out->devices;
1521 break;
1522 }
1523
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001524 // Treat as a special case when a1 and a2 are not disjoint
1525 if ((a1 != a2) && (a1 & a2)) {
1526 snd_device_t d3[2];
1527 int num_devices = 0;
1528 int ret = platform_split_snd_device(platform,
1529 popcount(a1) > 1 ? d1 : d2,
1530 &num_devices,
1531 d3);
1532 if (ret < 0) {
1533 if (ret != -ENOSYS) {
1534 ALOGW("%s failed to split snd_device %d",
1535 __func__,
1536 popcount(a1) > 1 ? d1 : d2);
1537 }
1538 goto end;
1539 }
1540
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001541 if (platform_check_backends_match(d3[0], d3[1])) {
1542 return d2; // case 5
1543 } else {
Samyak Jaind826b502019-07-17 16:16:42 +05301544 if (popcount(a1) > 1)
1545 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001546 // check if d1 is related to any of d3's
1547 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001548 return d1; // case 1
1549 else
1550 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001551 }
1552 } else {
1553 if (platform_check_backends_match(d1, d2)) {
1554 return d2; // case 2, 4
1555 } else {
1556 return d1; // case 6, 3
1557 }
1558 }
1559
1560end:
1561 return d2; // return whatever was calculated before.
1562}
1563
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301565 struct audio_usecase *uc_info,
1566 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567{
1568 struct listnode *node;
1569 struct audio_usecase *usecase;
1570 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301571 snd_device_t uc_derive_snd_device;
1572 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001573 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1574 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001575 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301576 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001577 /*
1578 * This function is to make sure that all the usecases that are active on
1579 * the hardware codec backend are always routed to any one device that is
1580 * handled by the hardware codec.
1581 * For example, if low-latency and deep-buffer usecases are currently active
1582 * on speaker and out_set_parameters(headset) is received on low-latency
1583 * output, then we have to make sure deep-buffer is also switched to headset,
1584 * because of the limitation that both the devices cannot be enabled
1585 * at the same time as they share the same backend.
1586 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001587 /*
1588 * This call is to check if we need to force routing for a particular stream
1589 * If there is a backend configuration change for the device when a
1590 * new stream starts, then ADM needs to be closed and re-opened with the new
1591 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001592 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001593 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001594 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1595 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301596 /* For a2dp device reconfigure all active sessions
1597 * with new AFE encoder format based on a2dp state
1598 */
1599 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1600 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1601 audio_extn_a2dp_is_force_device_switch()) {
1602 force_routing = true;
1603 force_restart_session = true;
1604 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301605 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1606
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001607 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001608 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001609 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001610 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1611 switch_device[i] = false;
1612
1613 list_for_each(node, &adev->usecase_list) {
1614 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001615
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301616 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1617 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301618 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301619 platform_get_snd_device_name(usecase->out_snd_device),
1620 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301621 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1622 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301623 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1624 usecase, uc_info, snd_device);
1625 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1626 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1627 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1628 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001629 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301630 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1631 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1632 ((force_restart_session) ||
1633 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301634 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1635 __func__, use_case_table[usecase->id],
1636 platform_get_snd_device_name(usecase->out_snd_device));
1637 disable_audio_route(adev, usecase);
1638 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301639 /* Enable existing usecase on derived playback device */
1640 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301641 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301642 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001643 }
1644 }
1645
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301646 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1647 num_uc_to_switch);
1648
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001649 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001650 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001651
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301652 /* Make sure the previous devices to be disabled first and then enable the
1653 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001654 list_for_each(node, &adev->usecase_list) {
1655 usecase = node_to_item(node, struct audio_usecase, list);
1656 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001657 /* Check if output sound device to be switched can be split and if any
1658 of the split devices match with derived sound device */
1659 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1660 &num_devices, split_snd_devices) == 0) {
1661 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1662 for (i = 0; i < num_devices; i++) {
1663 /* Disable devices that do not match with derived sound device */
1664 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1665 disable_snd_device(adev, split_snd_devices[i]);
1666 }
1667 } else {
1668 disable_snd_device(adev, usecase->out_snd_device);
1669 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001670 }
1671 }
1672
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001673 list_for_each(node, &adev->usecase_list) {
1674 usecase = node_to_item(node, struct audio_usecase, list);
1675 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001676 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1677 &num_devices, split_snd_devices) == 0) {
1678 /* Enable derived sound device only if it does not match with
1679 one of the split sound devices. This is because the matching
1680 sound device was not disabled */
1681 bool should_enable = true;
1682 for (i = 0; i < num_devices; i++) {
1683 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1684 should_enable = false;
1685 break;
1686 }
1687 }
1688 if (should_enable)
1689 enable_snd_device(adev, derive_snd_device[usecase->id]);
1690 } else {
1691 enable_snd_device(adev, derive_snd_device[usecase->id]);
1692 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001693 }
1694 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001695
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001696 /* Re-route all the usecases on the shared backend other than the
1697 specified usecase to new snd devices */
1698 list_for_each(node, &adev->usecase_list) {
1699 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301700 /* Update the out_snd_device only before enabling the audio route */
1701 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301702 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301703 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301704 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301705 use_case_table[usecase->id],
1706 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001707 /* Update voc calibration before enabling VoIP route */
1708 if (usecase->type == VOIP_CALL)
1709 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001710 usecase->out_snd_device,
1711 platform_get_input_snd_device(
1712 adev->platform, NULL,
1713 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301714 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301715 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001716 out_set_voip_volume(&usecase->stream.out->stream,
1717 usecase->stream.out->volume_l,
1718 usecase->stream.out->volume_r);
1719 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301720 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001721 }
1722 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001723 }
1724}
1725
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301726static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001727 struct audio_usecase *uc_info,
1728 snd_device_t snd_device)
1729{
1730 struct listnode *node;
1731 struct audio_usecase *usecase;
1732 bool switch_device[AUDIO_USECASE_MAX];
1733 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301734 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001735 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001736
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301737 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1738 snd_device);
1739 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301740
1741 /*
1742 * Make sure out devices is checked against out codec backend device and
1743 * also in devices against in codec backend. Checking out device against in
1744 * codec backend or vice versa causes issues.
1745 */
1746 if (uc_info->type == PCM_CAPTURE)
1747 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001748 /*
1749 * This function is to make sure that all the active capture usecases
1750 * are always routed to the same input sound device.
1751 * For example, if audio-record and voice-call usecases are currently
1752 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1753 * is received for voice call then we have to make sure that audio-record
1754 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1755 * because of the limitation that two devices cannot be enabled
1756 * at the same time if they share the same backend.
1757 */
1758 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1759 switch_device[i] = false;
1760
1761 list_for_each(node, &adev->usecase_list) {
1762 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301763 /*
1764 * TODO: Enhance below condition to handle BT sco/USB multi recording
1765 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001766 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001767 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301768 (usecase->in_snd_device != snd_device || force_routing) &&
juyuchen34574a02019-08-20 18:36:01 +08001769 (((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301770 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
juyuchen34574a02019-08-20 18:36:01 +08001771 (usecase->type == VOIP_CALL))) ||
Carter Hsu1d2a0532018-10-04 09:24:36 +08001772 ((uc_info->type == VOICE_CALL &&
1773 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1774 platform_check_backends_match(snd_device,\
juyuchen34574a02019-08-20 18:36:01 +08001775 usecase->in_snd_device))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001776 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001777 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1778 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001779 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001780 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001781 switch_device[usecase->id] = true;
1782 num_uc_to_switch++;
1783 }
1784 }
1785
1786 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001787 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001788
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301789 /* Make sure the previous devices to be disabled first and then enable the
1790 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001791 list_for_each(node, &adev->usecase_list) {
1792 usecase = node_to_item(node, struct audio_usecase, list);
1793 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001794 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001795 }
1796 }
1797
1798 list_for_each(node, &adev->usecase_list) {
1799 usecase = node_to_item(node, struct audio_usecase, list);
1800 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001801 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001802 }
1803 }
1804
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001805 /* Re-route all the usecases on the shared backend other than the
1806 specified usecase to new snd devices */
1807 list_for_each(node, &adev->usecase_list) {
1808 usecase = node_to_item(node, struct audio_usecase, list);
1809 /* Update the in_snd_device only before enabling the audio route */
1810 if (switch_device[usecase->id] ) {
1811 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001812 if (usecase->type != VOICE_CALL) {
1813 /* Update voc calibration before enabling VoIP route */
1814 if (usecase->type == VOIP_CALL)
1815 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001816 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001817 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301818 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001819 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001820 }
1821 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001822 }
1823}
1824
Mingming Yin3a941d42016-02-17 18:08:05 -08001825static void reset_hdmi_sink_caps(struct stream_out *out) {
1826 int i = 0;
1827
1828 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1829 out->supported_channel_masks[i] = 0;
1830 }
1831 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1832 out->supported_formats[i] = 0;
1833 }
1834 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1835 out->supported_sample_rates[i] = 0;
1836 }
1837}
1838
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001840static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001841{
Mingming Yin3a941d42016-02-17 18:08:05 -08001842 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001843 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001844
Mingming Yin3a941d42016-02-17 18:08:05 -08001845 reset_hdmi_sink_caps(out);
1846
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001847 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001848 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001849 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001850 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001851 }
1852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001853 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001854 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001855 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001856 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001857 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1858 case 6:
1859 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1860 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1861 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1862 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1863 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1864 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001865 break;
1866 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001867 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001868 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001869 break;
1870 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001871
1872 // check channel format caps
1873 i = 0;
1874 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1875 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1876 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1877 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1878 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1879 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1880 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1881 }
1882
Ben Romberger1aaaf862017-04-06 17:49:46 -07001883 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1884 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1885 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1886 }
1887
Mingming Yin3a941d42016-02-17 18:08:05 -08001888 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1889 ALOGV(":%s HDMI supports DTS format", __func__);
1890 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1891 }
1892
1893 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1894 ALOGV(":%s HDMI supports DTS HD format", __func__);
1895 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1896 }
1897
Naresh Tanniru928f0862017-04-07 16:44:23 -07001898 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1899 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1900 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1901 }
1902
Mingming Yin3a941d42016-02-17 18:08:05 -08001903
1904 // check sample rate caps
1905 i = 0;
1906 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1907 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1908 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1909 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1910 }
1911 }
1912
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001913 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001914}
1915
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001916static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1917 uint32_t *supported_sample_rates __unused,
1918 uint32_t max_rates __unused)
1919{
1920 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1921 supported_sample_rates,
1922 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301923 ssize_t i = 0;
1924
1925 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001926 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1927 supported_sample_rates[i]);
1928 }
1929 return count;
1930}
1931
1932static inline int read_usb_sup_channel_masks(bool is_playback,
1933 audio_channel_mask_t *supported_channel_masks,
1934 uint32_t max_masks)
1935{
1936 int channels = audio_extn_usb_get_max_channels(is_playback);
1937 int channel_count;
1938 uint32_t num_masks = 0;
1939 if (channels > MAX_HIFI_CHANNEL_COUNT)
1940 channels = MAX_HIFI_CHANNEL_COUNT;
1941
1942 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001943 // start from 2 channels as framework currently doesn't support mono.
1944 if (channels >= FCC_2) {
1945 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1946 }
1947 for (channel_count = FCC_2;
1948 channel_count <= channels && num_masks < max_masks;
1949 ++channel_count) {
1950 supported_channel_masks[num_masks++] =
1951 audio_channel_mask_for_index_assignment_from_count(channel_count);
1952 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001953 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001954 // For capture we report all supported channel masks from 1 channel up.
1955 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001956 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1957 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001958 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1959 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1960 if (channel_count <= FCC_2) {
1961 mask = audio_channel_in_mask_from_count(channel_count);
1962 supported_channel_masks[num_masks++] = mask;
1963 }
1964 const audio_channel_mask_t index_mask =
1965 audio_channel_mask_for_index_assignment_from_count(channel_count);
1966 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1967 supported_channel_masks[num_masks++] = index_mask;
1968 }
1969 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001970 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301971
vincenttewf51c94e2019-05-07 10:28:53 +08001972 for (size_t i = 0; i < num_masks; ++i) {
1973 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1974 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301975 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001976 return num_masks;
1977}
1978
1979static inline int read_usb_sup_formats(bool is_playback __unused,
1980 audio_format_t *supported_formats,
1981 uint32_t max_formats __unused)
1982{
1983 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1984 switch (bitwidth) {
1985 case 24:
1986 // XXX : usb.c returns 24 for s24 and s24_le?
1987 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1988 break;
1989 case 32:
1990 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1991 break;
1992 case 16:
1993 default :
1994 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1995 break;
1996 }
1997 ALOGV("%s: %s supported format %d", __func__,
1998 is_playback ? "P" : "C", bitwidth);
1999 return 1;
2000}
2001
2002static inline int read_usb_sup_params_and_compare(bool is_playback,
2003 audio_format_t *format,
2004 audio_format_t *supported_formats,
2005 uint32_t max_formats,
2006 audio_channel_mask_t *mask,
2007 audio_channel_mask_t *supported_channel_masks,
2008 uint32_t max_masks,
2009 uint32_t *rate,
2010 uint32_t *supported_sample_rates,
2011 uint32_t max_rates) {
2012 int ret = 0;
2013 int num_formats;
2014 int num_masks;
2015 int num_rates;
2016 int i;
2017
2018 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2019 max_formats);
2020 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2021 max_masks);
2022
2023 num_rates = read_usb_sup_sample_rates(is_playback,
2024 supported_sample_rates, max_rates);
2025
2026#define LUT(table, len, what, dflt) \
2027 for (i=0; i<len && (table[i] != what); i++); \
2028 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2029
2030 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2031 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2032 LUT(supported_sample_rates, num_rates, *rate, 0);
2033
2034#undef LUT
2035 return ret < 0 ? -EINVAL : 0; // HACK TBD
2036}
2037
Alexy Josephb1379942016-01-29 15:49:38 -08002038audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002039 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002040{
2041 struct audio_usecase *usecase;
2042 struct listnode *node;
2043
2044 list_for_each(node, &adev->usecase_list) {
2045 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002046 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002047 ALOGV("%s: usecase id %d", __func__, usecase->id);
2048 return usecase->id;
2049 }
2050 }
2051 return USECASE_INVALID;
2052}
2053
Alexy Josephb1379942016-01-29 15:49:38 -08002054struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002055 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002056{
2057 struct audio_usecase *usecase;
2058 struct listnode *node;
2059
2060 list_for_each(node, &adev->usecase_list) {
2061 usecase = node_to_item(node, struct audio_usecase, list);
2062 if (usecase->id == uc_id)
2063 return usecase;
2064 }
2065 return NULL;
2066}
2067
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302068/*
2069 * is a true native playback active
2070 */
2071bool audio_is_true_native_stream_active(struct audio_device *adev)
2072{
2073 bool active = false;
2074 int i = 0;
2075 struct listnode *node;
2076
2077 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2078 ALOGV("%s:napb: not in true mode or non hdphones device",
2079 __func__);
2080 active = false;
2081 goto exit;
2082 }
2083
2084 list_for_each(node, &adev->usecase_list) {
2085 struct audio_usecase *uc;
2086 uc = node_to_item(node, struct audio_usecase, list);
2087 struct stream_out *curr_out =
2088 (struct stream_out*) uc->stream.out;
2089
2090 if (curr_out && PCM_PLAYBACK == uc->type) {
2091 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2092 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2093 uc->id, curr_out->sample_rate,
2094 curr_out->bit_width,
2095 platform_get_snd_device_name(uc->out_snd_device));
2096
2097 if (is_offload_usecase(uc->id) &&
2098 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2099 active = true;
2100 ALOGD("%s:napb:native stream detected", __func__);
2101 }
2102 }
2103 }
2104exit:
2105 return active;
2106}
2107
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002108uint32_t adev_get_dsp_bit_width_enforce_mode()
2109{
2110 if (adev == NULL) {
2111 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2112 return 0;
2113 }
2114 return adev->dsp_bit_width_enforce_mode;
2115}
2116
2117static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2118{
2119 char value[PROPERTY_VALUE_MAX];
2120 int trial;
2121 uint32_t dsp_bit_width_enforce_mode = 0;
2122
2123 if (!mixer) {
2124 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2125 __func__);
2126 return 0;
2127 }
2128
2129 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2130 value, NULL) > 0) {
2131 trial = atoi(value);
2132 switch (trial) {
2133 case 16:
2134 dsp_bit_width_enforce_mode = 16;
2135 break;
2136 case 24:
2137 dsp_bit_width_enforce_mode = 24;
2138 break;
2139 case 32:
2140 dsp_bit_width_enforce_mode = 32;
2141 break;
2142 default:
2143 dsp_bit_width_enforce_mode = 0;
2144 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2145 break;
2146 }
2147 }
2148
2149 return dsp_bit_width_enforce_mode;
2150}
2151
2152static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2153 uint32_t enforce_mode,
2154 bool enable)
2155{
2156 struct mixer_ctl *ctl = NULL;
2157 const char *mixer_ctl_name = "ASM Bit Width";
2158 uint32_t asm_bit_width_mode = 0;
2159
2160 if (enforce_mode == 0) {
2161 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2162 return;
2163 }
2164
2165 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2166 if (!ctl) {
2167 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2168 __func__, mixer_ctl_name);
2169 return;
2170 }
2171
2172 if (enable)
2173 asm_bit_width_mode = enforce_mode;
2174 else
2175 asm_bit_width_mode = 0;
2176
2177 ALOGV("%s DSP bit width feature status is %d width=%d",
2178 __func__, enable, asm_bit_width_mode);
2179 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2180 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2181 asm_bit_width_mode);
2182
2183 return;
2184}
2185
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302186/*
2187 * if native DSD playback active
2188 */
2189bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2190{
2191 bool active = false;
2192 struct listnode *node = NULL;
2193 struct audio_usecase *uc = NULL;
2194 struct stream_out *curr_out = NULL;
2195
2196 list_for_each(node, &adev->usecase_list) {
2197 uc = node_to_item(node, struct audio_usecase, list);
2198 curr_out = (struct stream_out*) uc->stream.out;
2199
2200 if (curr_out && PCM_PLAYBACK == uc->type &&
2201 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2202 active = true;
2203 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302204 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302205 }
2206 }
2207 return active;
2208}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302209
2210static bool force_device_switch(struct audio_usecase *usecase)
2211{
2212 bool ret = false;
2213 bool is_it_true_mode = false;
2214
Zhou Song30f2c3e2018-02-08 14:02:15 +08002215 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302216 usecase->type == TRANSCODE_LOOPBACK_RX ||
2217 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002218 return false;
2219 }
2220
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002221 if(usecase->stream.out == NULL) {
2222 ALOGE("%s: stream.out is NULL", __func__);
2223 return false;
2224 }
2225
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302226 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002227 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2228 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2229 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302230 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2231 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2232 (!is_it_true_mode && adev->native_playback_enabled)){
2233 ret = true;
2234 ALOGD("napb: time to toggle native mode");
2235 }
2236 }
2237
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302238 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302239 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2240 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002241 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302242 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302243 ALOGD("Force a2dp device switch to update new encoder config");
2244 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002245 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302246
Florian Pfister1a84f312018-07-19 14:38:18 +02002247 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302248 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2249 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002250 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302251 return ret;
2252}
2253
Aalique Grahame22e49102018-12-18 14:23:57 -08002254static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2255{
2256 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2257}
2258
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302259bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2260{
2261 bool ret=false;
2262 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2263 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2264 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2265 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2266 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2267 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2268 ret = true;
2269
2270 return ret;
2271}
2272
2273bool is_a2dp_device(snd_device_t out_snd_device)
2274{
2275 bool ret=false;
2276 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2277 ret = true;
2278
2279 return ret;
2280}
2281
2282bool is_bt_soc_on(struct audio_device *adev)
2283{
2284 struct mixer_ctl *ctl;
2285 char *mixer_ctl_name = "BT SOC status";
2286 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2287 bool bt_soc_status = true;
2288 if (!ctl) {
2289 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2290 __func__, mixer_ctl_name);
2291 /*This is to ensure we dont break targets which dont have the kernel change*/
2292 return true;
2293 }
2294 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2295 ALOGD("BT SOC status: %d",bt_soc_status);
2296 return bt_soc_status;
2297}
2298
Zhou Song4721e282019-08-26 14:16:12 +08002299static int configure_btsco_sample_rate(snd_device_t snd_device)
2300{
2301 struct mixer_ctl *ctl = NULL;
2302 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2303 char *rate_str = NULL;
2304 bool is_rx_dev = true;
2305
2306 if (is_btsco_device(snd_device, snd_device)) {
2307 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2308 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2309 if (!ctl_sr_tx || !ctl_sr_rx) {
2310 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2311 if (!ctl_sr)
2312 return -ENOSYS;
2313 }
2314
2315 switch (snd_device) {
2316 case SND_DEVICE_OUT_BT_SCO:
2317 rate_str = "KHZ_8";
2318 break;
2319 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2320 case SND_DEVICE_IN_BT_SCO_MIC:
2321 rate_str = "KHZ_8";
2322 is_rx_dev = false;
2323 break;
2324 case SND_DEVICE_OUT_BT_SCO_WB:
2325 rate_str = "KHZ_16";
2326 break;
2327 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2328 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2329 rate_str = "KHZ_16";
2330 is_rx_dev = false;
2331 break;
2332 default:
2333 return 0;
2334 }
2335
2336 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2337 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2338 return -ENOSYS;
2339 }
2340 return 0;
2341}
2342
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302343int out_standby_l(struct audio_stream *stream);
2344
Eric Laurent637e2d42018-11-15 12:24:31 -08002345struct stream_in *adev_get_active_input(const struct audio_device *adev)
2346{
2347 struct listnode *node;
2348 struct stream_in *last_active_in = NULL;
2349
2350 /* Get last added active input.
2351 * TODO: We may use a priority mechanism to pick highest priority active source */
2352 list_for_each(node, &adev->usecase_list)
2353 {
2354 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2355 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2356 last_active_in = usecase->stream.in;
2357 }
2358
2359 return last_active_in;
2360}
2361
2362struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2363{
2364 struct listnode *node;
2365
2366 /* First check active inputs with voice communication source and then
2367 * any input if audio mode is in communication */
2368 list_for_each(node, &adev->usecase_list)
2369 {
2370 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2371 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2372 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2373 return usecase->stream.in;
2374 }
2375 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2376 return adev_get_active_input(adev);
2377
2378 return NULL;
2379}
2380
Carter Hsu2e429db2019-05-14 18:50:52 +08002381/*
2382 * Aligned with policy.h
2383 */
2384static inline int source_priority(int inputSource)
2385{
2386 switch (inputSource) {
2387 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2388 return 9;
2389 case AUDIO_SOURCE_CAMCORDER:
2390 return 8;
2391 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2392 return 7;
2393 case AUDIO_SOURCE_UNPROCESSED:
2394 return 6;
2395 case AUDIO_SOURCE_MIC:
2396 return 5;
2397 case AUDIO_SOURCE_ECHO_REFERENCE:
2398 return 4;
2399 case AUDIO_SOURCE_FM_TUNER:
2400 return 3;
2401 case AUDIO_SOURCE_VOICE_RECOGNITION:
2402 return 2;
2403 case AUDIO_SOURCE_HOTWORD:
2404 return 1;
2405 default:
2406 break;
2407 }
2408 return 0;
2409}
2410
2411static struct stream_in *get_priority_input(struct audio_device *adev)
2412{
2413 struct listnode *node;
2414 struct audio_usecase *usecase;
2415 int last_priority = 0, priority;
2416 struct stream_in *priority_in = NULL;
2417 struct stream_in *in;
2418
2419 list_for_each(node, &adev->usecase_list) {
2420 usecase = node_to_item(node, struct audio_usecase, list);
2421 if (usecase->type == PCM_CAPTURE) {
2422 in = usecase->stream.in;
2423 if (!in)
2424 continue;
2425 priority = source_priority(in->source);
2426
2427 if (priority > last_priority) {
2428 last_priority = priority;
2429 priority_in = in;
2430 }
2431 }
2432 }
2433 return priority_in;
2434}
2435
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002436int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002438 snd_device_t out_snd_device = SND_DEVICE_NONE;
2439 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002440 struct audio_usecase *usecase = NULL;
2441 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002442 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002443 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302444 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002445 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002446 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002447
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302448 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2449
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002450 usecase = get_usecase_from_list(adev, uc_id);
2451 if (usecase == NULL) {
2452 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2453 return -EINVAL;
2454 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002455
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002456 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002457 (usecase->type == VOIP_CALL) ||
2458 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302459 if(usecase->stream.out == NULL) {
2460 ALOGE("%s: stream.out is NULL", __func__);
2461 return -EINVAL;
2462 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002463 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002464 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002465 in_snd_device = platform_get_input_snd_device(adev->platform,
2466 NULL,
2467 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002468 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302469 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302470 if (usecase->stream.inout == NULL) {
2471 ALOGE("%s: stream.inout is NULL", __func__);
2472 return -EINVAL;
2473 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302474 stream_out.devices = usecase->stream.inout->out_config.devices;
2475 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2476 stream_out.format = usecase->stream.inout->out_config.format;
2477 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2478 out_snd_device = platform_get_output_snd_device(adev->platform,
2479 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302480 usecase->devices = out_snd_device;
2481 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2482 if (usecase->stream.inout == NULL) {
2483 ALOGE("%s: stream.inout is NULL", __func__);
2484 return -EINVAL;
2485 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002486 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302487 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002488 } else {
2489 /*
2490 * If the voice call is active, use the sound devices of voice call usecase
2491 * so that it would not result any device switch. All the usecases will
2492 * be switched to new device when select_devices() is called for voice call
2493 * usecase. This is to avoid switching devices for voice call when
2494 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002495 * choose voice call device only if the use case device is
2496 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002497 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002498 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002499 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002500 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002501 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2502 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302503 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2504 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002505 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2506 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002507 in_snd_device = vc_usecase->in_snd_device;
2508 out_snd_device = vc_usecase->out_snd_device;
2509 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002510 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002511 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002512 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002513 if ((voip_usecase != NULL) &&
2514 (usecase->type == PCM_PLAYBACK) &&
2515 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002516 out_snd_device_backend_match = platform_check_backends_match(
2517 voip_usecase->out_snd_device,
2518 platform_get_output_snd_device(
2519 adev->platform,
2520 usecase->stream.out));
2521 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002522 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002523 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2524 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002525 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002526 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002527 in_snd_device = voip_usecase->in_snd_device;
2528 out_snd_device = voip_usecase->out_snd_device;
2529 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002530 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002531 hfp_ucid = audio_extn_hfp_get_usecase();
2532 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002533 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002534 in_snd_device = hfp_usecase->in_snd_device;
2535 out_snd_device = hfp_usecase->out_snd_device;
2536 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002537 }
2538 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302539 if (usecase->stream.out == NULL) {
2540 ALOGE("%s: stream.out is NULL", __func__);
2541 return -EINVAL;
2542 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002543 usecase->devices = usecase->stream.out->devices;
2544 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002545 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002546 struct stream_out *voip_out = adev->primary_output;
2547 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002548 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002549 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002550 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002551
Eric Laurent637e2d42018-11-15 12:24:31 -08002552 if (voip_usecase)
2553 voip_out = voip_usecase->stream.out;
2554
2555 if (usecase->stream.out == voip_out && voip_in != NULL)
2556 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002557 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002558 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302559 if (usecase->stream.in == NULL) {
2560 ALOGE("%s: stream.in is NULL", __func__);
2561 return -EINVAL;
2562 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002563 usecase->devices = usecase->stream.in->device;
2564 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002565 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002566 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002567 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002568 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002569
2570 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002571 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2572 USECASE_AUDIO_PLAYBACK_VOIP);
2573
Carter Hsu2e429db2019-05-14 18:50:52 +08002574 usecase->stream.in->enable_ec_port = false;
2575
Eric Laurent637e2d42018-11-15 12:24:31 -08002576 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2577 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2578 } else if (voip_usecase) {
2579 out_device = voip_usecase->stream.out->devices;
2580 } else if (adev->primary_output &&
2581 !adev->primary_output->standby) {
2582 out_device = adev->primary_output->devices;
2583 } else {
2584 /* forcing speaker o/p device to get matching i/p pair
2585 in case o/p is not routed from same primary HAL */
2586 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2587 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002588 priority_in = voip_in;
2589 } else {
2590 /* get the input with the highest priority source*/
2591 priority_in = get_priority_input(adev);
2592
2593 if (!priority_in)
2594 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002595 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002596
Eric Laurent637e2d42018-11-15 12:24:31 -08002597 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002598 priority_in,
Eric Laurent637e2d42018-11-15 12:24:31 -08002599 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002600 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002601 }
2602 }
2603
2604 if (out_snd_device == usecase->out_snd_device &&
2605 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302606
2607 if (!force_device_switch(usecase))
2608 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 }
2610
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302611 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002612 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302613 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2614 return 0;
2615 }
2616
Aalique Grahame22e49102018-12-18 14:23:57 -08002617 if (out_snd_device != SND_DEVICE_NONE &&
2618 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2619 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2620 __func__,
2621 use_case_table[uc_id],
2622 adev->last_logged_snd_device[uc_id][0],
2623 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2624 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2625 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2626 -1,
2627 out_snd_device,
2628 platform_get_snd_device_name(out_snd_device),
2629 platform_get_snd_device_acdb_id(out_snd_device));
2630 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2631 }
2632 if (in_snd_device != SND_DEVICE_NONE &&
2633 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2634 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2635 __func__,
2636 use_case_table[uc_id],
2637 adev->last_logged_snd_device[uc_id][1],
2638 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2639 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2640 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2641 -1,
2642 in_snd_device,
2643 platform_get_snd_device_name(in_snd_device),
2644 platform_get_snd_device_acdb_id(in_snd_device));
2645 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2646 }
2647
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 /*
2650 * Limitation: While in call, to do a device switch we need to disable
2651 * and enable both RX and TX devices though one of them is same as current
2652 * device.
2653 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002654 if ((usecase->type == VOICE_CALL) &&
2655 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2656 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002657 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002658 }
2659
2660 if (((usecase->type == VOICE_CALL) ||
2661 (usecase->type == VOIP_CALL)) &&
2662 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2663 /* Disable sidetone only if voice/voip call already exists */
2664 if (voice_is_call_state_active(adev) ||
2665 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002666 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002667
2668 /* Disable aanc only if voice call exists */
2669 if (voice_is_call_state_active(adev))
2670 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002671 }
2672
Aalique Grahame22e49102018-12-18 14:23:57 -08002673 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2674 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002675 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302676 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002677 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2678 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2679 else
2680 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302681 }
2682
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002683 /* Disable current sound devices */
2684 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002685 disable_audio_route(adev, usecase);
2686 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687 }
2688
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002689 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002690 disable_audio_route(adev, usecase);
2691 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 }
2693
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002694 /* Applicable only on the targets that has external modem.
2695 * New device information should be sent to modem before enabling
2696 * the devices to reduce in-call device switch time.
2697 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002698 if ((usecase->type == VOICE_CALL) &&
2699 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2700 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002701 status = platform_switch_voice_call_enable_device_config(adev->platform,
2702 out_snd_device,
2703 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002704 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002705
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002706 /* Enable new sound devices */
2707 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002708 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302709 if (platform_check_codec_asrc_support(adev->platform))
2710 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002711 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 }
2713
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002714 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302715 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002716 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002717 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002718
Avinash Vaish71a8b972014-07-24 15:36:33 +05302719 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002720 status = platform_switch_voice_call_device_post(adev->platform,
2721 out_snd_device,
2722 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302723 enable_audio_route_for_voice_usecases(adev, usecase);
2724 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002725
sangwoo170731f2013-06-08 15:36:36 +09002726 usecase->in_snd_device = in_snd_device;
2727 usecase->out_snd_device = out_snd_device;
2728
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302729 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2730 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302731 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002732 if ((24 == usecase->stream.out->bit_width) &&
2733 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2734 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2735 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2736 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2737 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2738 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2739 /*
2740 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2741 * configured device sample rate, if not update the COPP rate to be equal to the
2742 * device sample rate, else open COPP at stream sample rate
2743 */
2744 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2745 usecase->stream.out->sample_rate,
2746 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302747 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
Preetam Singh Ranawate3af5102019-09-30 14:39:47 +05302748 out_snd_device != SND_DEVICE_OUT_HEADPHONES &&
2749 out_snd_device != SND_DEVICE_OUT_HEADPHONES_HIFI_FILTER &&
Ashish Jain4826f6c2017-02-06 13:33:20 +05302750 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002751 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2752 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2753 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2754 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002755 }
2756 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002757
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002758 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002759
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002760 /* If input stream is already running then effect needs to be
2761 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002762 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002763 check_and_enable_effect(adev);
2764
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002765 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002766 /* Enable aanc only if voice call exists */
2767 if (voice_is_call_state_active(adev))
2768 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2769
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002770 /* Enable sidetone only if other voice/voip call already exists */
2771 if (voice_is_call_state_active(adev) ||
2772 voice_extn_compress_voip_is_started(adev))
2773 voice_set_sidetone(adev, out_snd_device, true);
2774 }
2775
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002776 /* Applicable only on the targets that has external modem.
2777 * Enable device command should be sent to modem only after
2778 * enabling voice call mixer controls
2779 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002780 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002781 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2782 out_snd_device,
2783 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302784
2785 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002786 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302787 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002788 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302789 if (is_bt_soc_on(adev) == false){
2790 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002791 if (in->pcm != NULL)
2792 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302793 }
2794 }
2795 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2796 && usecase->stream.out->started) {
2797 if (is_bt_soc_on(adev) == false) {
2798 ALOGD("BT SCO/A2DP disconnected while in connection");
2799 out_standby_l(&usecase->stream.out->stream.common);
2800 }
2801 }
2802 } else if ((usecase->stream.out != NULL) &&
2803 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302804 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2805 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Weiyin Jiang0791c8e2019-07-25 13:18:17 +08002806 (usecase->type != PCM_CAPTURE) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302807 usecase->stream.out->started) {
2808 if (is_bt_soc_on(adev) == false) {
2809 ALOGD("BT SCO/A2dp disconnected while in connection");
2810 out_standby_l(&usecase->stream.out->stream.common);
2811 }
2812 }
2813 }
2814
Yung Ti Su70cb8242018-06-22 17:38:47 +08002815 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002816 struct stream_out *voip_out = voip_usecase->stream.out;
2817 audio_extn_utils_send_app_type_gain(adev,
2818 voip_out->app_type_cfg.app_type,
2819 &voip_out->app_type_cfg.gain[0]);
2820 }
2821
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302822 ALOGD("%s: done",__func__);
2823
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002824 return status;
2825}
2826
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002827static int stop_input_stream(struct stream_in *in)
2828{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302829 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002830 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302831
2832 if (in == NULL) {
2833 ALOGE("%s: stream_in ptr is NULL", __func__);
2834 return -EINVAL;
2835 }
2836
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002838 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002839
Eric Laurent994a6932013-07-17 11:51:42 -07002840 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002841 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002842 uc_info = get_usecase_from_list(adev, in->usecase);
2843 if (uc_info == NULL) {
2844 ALOGE("%s: Could not find the usecase (%d) in the list",
2845 __func__, in->usecase);
2846 return -EINVAL;
2847 }
2848
Carter Hsu2e429db2019-05-14 18:50:52 +08002849 priority_in = get_priority_input(adev);
2850
Derek Chenea197282019-01-07 17:35:01 -08002851 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2852 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002853
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002854 /* Close in-call recording streams */
2855 voice_check_and_stop_incall_rec_usecase(adev, in);
2856
Eric Laurent150dbfe2013-02-27 14:31:02 -08002857 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002858 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002859
2860 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002861 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002862
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05302863 if (is_loopback_input_device(in->device))
2864 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
2865
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002866 list_remove(&uc_info->list);
2867 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002868
Carter Hsu2e429db2019-05-14 18:50:52 +08002869 if (priority_in == in) {
2870 priority_in = get_priority_input(adev);
2871 if (priority_in)
2872 select_devices(adev, priority_in->usecase);
2873 }
2874
Vatsal Buchac09ae062018-11-14 13:25:08 +05302875 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002876 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002877 return ret;
2878}
2879
2880int start_input_stream(struct stream_in *in)
2881{
2882 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002883 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002884 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302885
2886 if (in == NULL) {
2887 ALOGE("%s: stream_in ptr is NULL", __func__);
2888 return -EINVAL;
2889 }
2890
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002891 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002892 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002893 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002894
Mingming Yin2664a5b2015-09-03 10:53:11 -07002895 if (get_usecase_from_list(adev, usecase) == NULL)
2896 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302897 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2898 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002899
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302900 if (CARD_STATUS_OFFLINE == in->card_status||
2901 CARD_STATUS_OFFLINE == adev->card_status) {
2902 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302903 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302904 goto error_config;
2905 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302906
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302907 if (audio_is_bluetooth_sco_device(in->device)) {
2908 if (!adev->bt_sco_on) {
2909 ALOGE("%s: SCO profile is not ready, return error", __func__);
2910 ret = -EIO;
2911 goto error_config;
2912 }
2913 }
2914
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002915 /* Check if source matches incall recording usecase criteria */
2916 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2917 if (ret)
2918 goto error_config;
2919 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002920 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2921
2922 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2923 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2924 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002925 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002926 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002927
Eric Laurentb23d5282013-05-14 15:27:20 -07002928 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 if (in->pcm_device_id < 0) {
2930 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2931 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002932 ret = -EINVAL;
2933 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002934 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002935
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002936 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002937
2938 if (!uc_info) {
2939 ret = -ENOMEM;
2940 goto error_config;
2941 }
2942
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002943 uc_info->id = in->usecase;
2944 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002945 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002946 uc_info->devices = in->device;
2947 uc_info->in_snd_device = SND_DEVICE_NONE;
2948 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002949
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002950 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002951 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302952 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2953 adev->perf_lock_opts,
2954 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002955 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002956
Derek Chenea197282019-01-07 17:35:01 -08002957 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2958 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002959
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05302960 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
2961
Haynes Mathew George16081042017-05-31 17:16:49 -07002962 if (audio_extn_cin_attached_usecase(in->usecase)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05302963 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302964 if (ret)
2965 goto error_open;
2966 else
2967 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002968 }
2969
Haynes Mathew George16081042017-05-31 17:16:49 -07002970 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002971 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002972 ALOGE("%s: pcm stream not ready", __func__);
2973 goto error_open;
2974 }
2975 ret = pcm_start(in->pcm);
2976 if (ret < 0) {
2977 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2978 goto error_open;
2979 }
2980 } else {
2981 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2982 unsigned int pcm_open_retry_count = 0;
2983
2984 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2985 flags |= PCM_MMAP | PCM_NOIRQ;
2986 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2987 } else if (in->realtime) {
2988 flags |= PCM_MMAP | PCM_NOIRQ;
2989 }
2990
Garmond Leunge2433c32017-09-28 21:51:22 -07002991 if (audio_extn_ffv_get_stream() == in) {
2992 ALOGD("%s: ffv stream, update pcm config", __func__);
2993 audio_extn_ffv_update_pcm_config(&config);
2994 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002995 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2996 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2997
2998 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002999 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07003000 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07003001 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003002 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303003 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303004 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3005 adev->card_status = CARD_STATUS_OFFLINE;
3006 in->card_status = CARD_STATUS_OFFLINE;
3007 ret = -EIO;
3008 goto error_open;
3009 }
3010
Haynes Mathew George16081042017-05-31 17:16:49 -07003011 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3012 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3013 if (in->pcm != NULL) {
3014 pcm_close(in->pcm);
3015 in->pcm = NULL;
3016 }
3017 if (pcm_open_retry_count-- == 0) {
3018 ret = -EIO;
3019 goto error_open;
3020 }
3021 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3022 continue;
3023 }
3024 break;
3025 }
3026
3027 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003028 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003029 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003030 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003031 if (ret < 0) {
3032 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3033 pcm_close(in->pcm);
3034 in->pcm = NULL;
3035 goto error_open;
3036 }
3037 register_in_stream(in);
3038 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003039 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003040 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003041 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003042 if (ret < 0) {
3043 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003044 pcm_close(in->pcm);
3045 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003046 goto error_open;
3047 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003048 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003049 }
3050
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003051 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003052 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3053 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003054
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303055 if (is_loopback_input_device(in->device))
3056 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3057
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303058done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003059 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303060 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003061 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303062 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003063 return ret;
3064
3065error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003066 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303067 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003068 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003069
Eric Laurentc8400632013-02-14 19:04:54 -08003070error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303071 /*
3072 * sleep 50ms to allow sufficient time for kernel
3073 * drivers to recover incases like SSR.
3074 */
3075 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003076 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303077 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003078 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003079}
3080
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003081void lock_input_stream(struct stream_in *in)
3082{
3083 pthread_mutex_lock(&in->pre_lock);
3084 pthread_mutex_lock(&in->lock);
3085 pthread_mutex_unlock(&in->pre_lock);
3086}
3087
3088void lock_output_stream(struct stream_out *out)
3089{
3090 pthread_mutex_lock(&out->pre_lock);
3091 pthread_mutex_lock(&out->lock);
3092 pthread_mutex_unlock(&out->pre_lock);
3093}
3094
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095/* must be called with out->lock locked */
3096static int send_offload_cmd_l(struct stream_out* out, int command)
3097{
3098 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3099
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003100 if (!cmd) {
3101 ALOGE("failed to allocate mem for command 0x%x", command);
3102 return -ENOMEM;
3103 }
3104
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003105 ALOGVV("%s %d", __func__, command);
3106
3107 cmd->cmd = command;
3108 list_add_tail(&out->offload_cmd_list, &cmd->node);
3109 pthread_cond_signal(&out->offload_cond);
3110 return 0;
3111}
3112
3113/* must be called iwth out->lock locked */
3114static void stop_compressed_output_l(struct stream_out *out)
3115{
3116 out->offload_state = OFFLOAD_STATE_IDLE;
3117 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003118 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003119 if (out->compr != NULL) {
3120 compress_stop(out->compr);
3121 while (out->offload_thread_blocked) {
3122 pthread_cond_wait(&out->cond, &out->lock);
3123 }
3124 }
3125}
3126
Varun Balaraje49253e2017-07-06 19:48:56 +05303127bool is_interactive_usecase(audio_usecase_t uc_id)
3128{
3129 unsigned int i;
3130 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3131 if (uc_id == interactive_usecases[i])
3132 return true;
3133 }
3134 return false;
3135}
3136
3137static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3138{
3139 audio_usecase_t ret_uc = USECASE_INVALID;
3140 unsigned int intract_uc_index;
3141 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3142
3143 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3144 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3145 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3146 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3147 ret_uc = interactive_usecases[intract_uc_index];
3148 break;
3149 }
3150 }
3151
3152 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3153 return ret_uc;
3154}
3155
3156static void free_interactive_usecase(struct audio_device *adev,
3157 audio_usecase_t uc_id)
3158{
3159 unsigned int interact_uc_index;
3160 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3161
3162 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3163 if (interactive_usecases[interact_uc_index] == uc_id) {
3164 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3165 break;
3166 }
3167 }
3168 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3169}
3170
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003171bool is_offload_usecase(audio_usecase_t uc_id)
3172{
3173 unsigned int i;
3174 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3175 if (uc_id == offload_usecases[i])
3176 return true;
3177 }
3178 return false;
3179}
3180
Dhananjay Kumarac341582017-02-23 23:42:25 +05303181static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003182{
vivek mehta446c3962015-09-14 10:57:35 -07003183 audio_usecase_t ret_uc = USECASE_INVALID;
3184 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003185 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003186 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303187 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003188 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3189 else
3190 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003191
vivek mehta446c3962015-09-14 10:57:35 -07003192 pthread_mutex_lock(&adev->lock);
3193 if (get_usecase_from_list(adev, ret_uc) != NULL)
3194 ret_uc = USECASE_INVALID;
3195 pthread_mutex_unlock(&adev->lock);
3196
3197 return ret_uc;
3198 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003199
3200 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003201 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3202 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3203 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3204 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003205 break;
3206 }
3207 }
vivek mehta446c3962015-09-14 10:57:35 -07003208
3209 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3210 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003211}
3212
3213static void free_offload_usecase(struct audio_device *adev,
3214 audio_usecase_t uc_id)
3215{
vivek mehta446c3962015-09-14 10:57:35 -07003216 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003217 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003218
3219 if (!adev->multi_offload_enable)
3220 return;
3221
3222 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3223 if (offload_usecases[offload_uc_index] == uc_id) {
3224 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003225 break;
3226 }
3227 }
3228 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3229}
3230
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003231static void *offload_thread_loop(void *context)
3232{
3233 struct stream_out *out = (struct stream_out *) context;
3234 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003235 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003236
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003237 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Weiyin Jiangebfa0502019-07-18 17:24:21 +08003238 set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003239 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3240
3241 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003242 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003243 out->offload_state = OFFLOAD_STATE_IDLE;
3244 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003245 for (;;) {
3246 struct offload_cmd *cmd = NULL;
3247 stream_callback_event_t event;
3248 bool send_callback = false;
3249
3250 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3251 __func__, list_empty(&out->offload_cmd_list),
3252 out->offload_state);
3253 if (list_empty(&out->offload_cmd_list)) {
3254 ALOGV("%s SLEEPING", __func__);
3255 pthread_cond_wait(&out->offload_cond, &out->lock);
3256 ALOGV("%s RUNNING", __func__);
3257 continue;
3258 }
3259
3260 item = list_head(&out->offload_cmd_list);
3261 cmd = node_to_item(item, struct offload_cmd, node);
3262 list_remove(item);
3263
3264 ALOGVV("%s STATE %d CMD %d out->compr %p",
3265 __func__, out->offload_state, cmd->cmd, out->compr);
3266
3267 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3268 free(cmd);
3269 break;
3270 }
3271
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003272 // allow OFFLOAD_CMD_ERROR reporting during standby
3273 // this is needed to handle failures during compress_open
3274 // Note however that on a pause timeout, the stream is closed
3275 // and no offload usecase will be active. Therefore this
3276 // special case is needed for compress_open failures alone
3277 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3278 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003279 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003280 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003281 pthread_cond_signal(&out->cond);
3282 continue;
3283 }
3284 out->offload_thread_blocked = true;
3285 pthread_mutex_unlock(&out->lock);
3286 send_callback = false;
3287 switch(cmd->cmd) {
3288 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003289 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003290 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003291 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003292 send_callback = true;
3293 event = STREAM_CBK_EVENT_WRITE_READY;
3294 break;
3295 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003296 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303297 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003298 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303299 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003300 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303301 if (ret < 0)
3302 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303303 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303304 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003305 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003306 else
3307 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003308 if (-ENETRESET != ret && !(-EINTR == ret &&
3309 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303310 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303311 pthread_mutex_lock(&out->lock);
3312 out->send_new_metadata = 1;
3313 out->send_next_track_params = true;
3314 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303315 event = STREAM_CBK_EVENT_DRAIN_READY;
3316 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3317 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303318 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003319 break;
3320 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003321 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003322 ret = compress_drain(out->compr);
3323 ALOGD("copl(%p):out of compress_drain", out);
3324 // EINTR check avoids drain interruption due to SSR
3325 if (-ENETRESET != ret && !(-EINTR == ret &&
3326 CARD_STATUS_OFFLINE == out->card_status)) {
3327 send_callback = true;
3328 event = STREAM_CBK_EVENT_DRAIN_READY;
3329 } else
3330 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003331 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303332 case OFFLOAD_CMD_ERROR:
3333 ALOGD("copl(%p): sending error callback to AF", out);
3334 send_callback = true;
3335 event = STREAM_CBK_EVENT_ERROR;
3336 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003337 default:
3338 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3339 break;
3340 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003341 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003342 out->offload_thread_blocked = false;
3343 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003344 if (send_callback && out->client_callback) {
3345 ALOGVV("%s: sending client_callback event %d", __func__, event);
3346 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003347 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003348 free(cmd);
3349 }
3350
3351 pthread_cond_signal(&out->cond);
3352 while (!list_empty(&out->offload_cmd_list)) {
3353 item = list_head(&out->offload_cmd_list);
3354 list_remove(item);
3355 free(node_to_item(item, struct offload_cmd, node));
3356 }
3357 pthread_mutex_unlock(&out->lock);
3358
3359 return NULL;
3360}
3361
3362static int create_offload_callback_thread(struct stream_out *out)
3363{
3364 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3365 list_init(&out->offload_cmd_list);
3366 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3367 offload_thread_loop, out);
3368 return 0;
3369}
3370
3371static int destroy_offload_callback_thread(struct stream_out *out)
3372{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003373 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003374 stop_compressed_output_l(out);
3375 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3376
3377 pthread_mutex_unlock(&out->lock);
3378 pthread_join(out->offload_thread, (void **) NULL);
3379 pthread_cond_destroy(&out->offload_cond);
3380
3381 return 0;
3382}
3383
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003384static int stop_output_stream(struct stream_out *out)
3385{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303386 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003387 struct audio_usecase *uc_info;
3388 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003389 bool has_voip_usecase =
3390 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003391
Eric Laurent994a6932013-07-17 11:51:42 -07003392 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003393 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003394 uc_info = get_usecase_from_list(adev, out->usecase);
3395 if (uc_info == NULL) {
3396 ALOGE("%s: Could not find the usecase (%d) in the list",
3397 __func__, out->usecase);
3398 return -EINVAL;
3399 }
3400
Derek Chenea197282019-01-07 17:35:01 -08003401 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3402 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003403
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003404 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303405 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003406 if (adev->visualizer_stop_output != NULL)
3407 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003408
3409 audio_extn_dts_remove_state_notifier_node(out->usecase);
3410
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003411 if (adev->offload_effects_stop_output != NULL)
3412 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003413 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3414 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3415 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003416 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003417
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003418 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3419 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003420 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003421 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003422
Eric Laurent150dbfe2013-02-27 14:31:02 -08003423 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003424 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003425
3426 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003427 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003428
Aalique Grahame22e49102018-12-18 14:23:57 -08003429 audio_extn_extspk_update(adev->extspk);
3430
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003431 if (is_offload_usecase(out->usecase)) {
3432 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3433 adev->dsp_bit_width_enforce_mode,
3434 false);
3435 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003436 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3437 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3438 false);
3439
3440 if (ret != 0)
3441 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3442 /* default service interval was successfully updated,
3443 reopen USB backend with new service interval */
3444 ret = 0;
3445 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003446
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003447 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303448 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003449 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303450 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003451 ALOGV("Disable passthrough , reset mixer to pcm");
3452 /* NO_PASSTHROUGH */
3453 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003454 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003455 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3456 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003457
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303458 /* Must be called after removing the usecase from list */
3459 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303460 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303461
Manish Dewangan21a850a2017-08-14 12:03:55 +05303462 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003463 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3464 if (ret < 0)
3465 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3466 }
3467
juyuchen2d415992018-11-16 14:15:16 +08003468 /* 1) media + voip output routing to handset must route media back to
3469 speaker when voip stops.
3470 2) trigger voip input to reroute when voip output changes to
3471 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003472 if (has_voip_usecase ||
3473 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3474 struct listnode *node;
3475 struct audio_usecase *usecase;
3476 list_for_each(node, &adev->usecase_list) {
3477 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003478 if ((usecase->type == PCM_CAPTURE &&
3479 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3480 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003481 continue;
3482
3483 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3484 __func__, usecase->id, use_case_table[usecase->id],
3485 out->usecase, use_case_table[out->usecase]);
3486 select_devices(adev, usecase->id);
3487 }
3488 }
3489
Garmond Leung5fd0b552018-04-17 11:56:12 -07003490 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003491 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003492 return ret;
3493}
3494
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003495struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3496 unsigned int flags, unsigned int pcm_open_retry_count,
3497 struct pcm_config *config)
3498{
3499 struct pcm* pcm = NULL;
3500
3501 while (1) {
3502 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3503 if (pcm == NULL || !pcm_is_ready(pcm)) {
3504 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3505 if (pcm != NULL) {
3506 pcm_close(pcm);
3507 pcm = NULL;
3508 }
3509 if (pcm_open_retry_count-- == 0)
3510 return NULL;
3511
3512 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3513 continue;
3514 }
3515 break;
3516 }
3517
3518 if (pcm_is_ready(pcm)) {
3519 int ret = pcm_prepare(pcm);
3520 if (ret < 0) {
3521 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3522 pcm_close(pcm);
3523 pcm = NULL;
3524 }
3525 }
3526
3527 return pcm;
3528}
3529
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003530int start_output_stream(struct stream_out *out)
3531{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003532 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003533 struct audio_usecase *uc_info;
3534 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003535 char mixer_ctl_name[128];
3536 struct mixer_ctl *ctl = NULL;
3537 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303538 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003539 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003540
Haynes Mathew George380745d2017-10-04 15:27:45 -07003541 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003542 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3543 ret = -EINVAL;
3544 goto error_config;
3545 }
3546
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003547 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303548 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003549 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303550
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303551 if (CARD_STATUS_OFFLINE == out->card_status ||
3552 CARD_STATUS_OFFLINE == adev->card_status) {
3553 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303554 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303555 goto error_config;
3556 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303557
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003558 //Update incall music usecase to reflect correct voice session
3559 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3560 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3561 if (ret != 0) {
3562 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3563 __func__, ret);
3564 goto error_config;
3565 }
3566 }
3567
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303568 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003569 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003570 if (out->devices &
3571 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303572 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303573 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303574 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3575 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3576 ret = -EAGAIN;
3577 goto error_config;
3578 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303579 }
3580 }
3581 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303582 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3583 if (!adev->bt_sco_on) {
3584 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3585 //combo usecase just by pass a2dp
3586 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3587 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3588 } else {
3589 ALOGE("%s: SCO profile is not ready, return error", __func__);
3590 ret = -EAGAIN;
3591 goto error_config;
3592 }
3593 }
3594 }
3595
Eric Laurentb23d5282013-05-14 15:27:20 -07003596 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597 if (out->pcm_device_id < 0) {
3598 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3599 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003600 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003601 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003602 }
3603
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003604 if (is_haptic_usecase) {
3605 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3606 if (adev->haptic_pcm_device_id < 0) {
3607 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3608 __func__, adev->haptic_pcm_device_id, out->usecase);
3609 ret = -EINVAL;
3610 goto error_config;
3611 }
3612 }
3613
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003614 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003615
3616 if (!uc_info) {
3617 ret = -ENOMEM;
3618 goto error_config;
3619 }
3620
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 uc_info->id = out->usecase;
3622 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003623 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003624 uc_info->devices = out->devices;
3625 uc_info->in_snd_device = SND_DEVICE_NONE;
3626 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003627
3628 /* This must be called before adding this usecase to the list */
3629 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3630 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3631 /* USB backend is not reopened immediately.
3632 This is eventually done as part of select_devices */
3633 }
3634
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003635 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003636
Wei Wangf7ca6c92017-11-21 14:51:20 -08003637 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303638 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3639 adev->perf_lock_opts,
3640 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303641
3642 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303643 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303644 if (audio_extn_passthru_is_enabled() &&
3645 audio_extn_passthru_is_passthrough_stream(out)) {
3646 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303647 }
3648 }
3649
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303650 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003651 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303652 if (!a2dp_combo) {
3653 check_a2dp_restore_l(adev, out, false);
3654 } else {
3655 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003656 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3657 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3658 else
3659 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303660 select_devices(adev, out->usecase);
3661 out->devices = dev;
3662 }
3663 } else {
3664 select_devices(adev, out->usecase);
3665 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003666
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003667 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3668 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003669 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003670 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003671
Derek Chenea197282019-01-07 17:35:01 -08003672 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3673 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003674
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003675 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3676 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003677
3678 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003679 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003680 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3681 ALOGE("%s: pcm stream not ready", __func__);
3682 goto error_open;
3683 }
3684 ret = pcm_start(out->pcm);
3685 if (ret < 0) {
3686 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3687 goto error_open;
3688 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003689 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003690 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003691 unsigned int flags = PCM_OUT;
3692 unsigned int pcm_open_retry_count = 0;
3693 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3694 flags |= PCM_MMAP | PCM_NOIRQ;
3695 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003696 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003697 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003698 } else
3699 flags |= PCM_MONOTONIC;
3700
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003701 if ((adev->vr_audio_mode_enabled) &&
3702 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3703 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3704 "PCM_Dev %d Topology", out->pcm_device_id);
3705 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3706 if (!ctl) {
3707 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3708 __func__, mixer_ctl_name);
3709 } else {
3710 //if success use ULLPP
3711 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3712 __func__, mixer_ctl_name, out->pcm_device_id);
3713 //There is a still a possibility that some sessions
3714 // that request for FAST|RAW when 3D audio is active
3715 //can go through ULLPP. Ideally we expects apps to
3716 //listen to audio focus and stop concurrent playback
3717 //Also, we will look for mode flag (voice_in_communication)
3718 //before enabling the realtime flag.
3719 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3720 }
3721 }
3722
Surendar Karka91fa3682018-07-02 18:12:12 +05303723 if (out->realtime)
3724 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3725 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3726
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003727 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3728 flags, pcm_open_retry_count,
3729 &(out->config));
3730 if (out->pcm == NULL) {
3731 ret = -EIO;
3732 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003733 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003734
3735 if (is_haptic_usecase) {
3736 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3737 adev->haptic_pcm_device_id,
3738 flags, pcm_open_retry_count,
3739 &(adev->haptics_config));
3740 // failure to open haptics pcm shouldnt stop audio,
3741 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003742
3743 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3744 ALOGD("%s: enable haptic audio synchronization", __func__);
3745 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3746 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003747 }
3748
Surendar Karka91fa3682018-07-02 18:12:12 +05303749 if (!out->realtime)
3750 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303751 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003752
Zhou Song2b8f28f2017-09-11 10:51:38 +08003753 // apply volume for voip playback after path is set up
3754 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3755 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303756 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3757 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303758 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3759 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003760 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3761 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303762 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003763 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003764 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303765 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003766 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3767 adev->dsp_bit_width_enforce_mode,
3768 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003769 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003770 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003771 out->compr = compress_open(adev->snd_card,
3772 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003773 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003774 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303775 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303776 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3777 adev->card_status = CARD_STATUS_OFFLINE;
3778 out->card_status = CARD_STATUS_OFFLINE;
3779 ret = -EIO;
3780 goto error_open;
3781 }
3782
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003783 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003784 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003785 compress_close(out->compr);
3786 out->compr = NULL;
3787 ret = -EIO;
3788 goto error_open;
3789 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303790 /* compress_open sends params of the track, so reset the flag here */
3791 out->is_compr_metadata_avail = false;
3792
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003793 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003794 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003795
Fred Oh3f43e742015-03-04 18:42:34 -08003796 /* Since small bufs uses blocking writes, a write will be blocked
3797 for the default max poll time (20s) in the event of an SSR.
3798 Reduce the poll time to observe and deal with SSR faster.
3799 */
Ashish Jain5106d362016-05-11 19:23:33 +05303800 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003801 compress_set_max_poll_wait(out->compr, 1000);
3802 }
3803
Manish Dewangan69426c82017-01-30 17:35:36 +05303804 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303805 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303806
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003807 audio_extn_dts_create_state_notifier_node(out->usecase);
3808 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3809 popcount(out->channel_mask),
3810 out->playback_started);
3811
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003812#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303813 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003814 audio_extn_dolby_send_ddp_endp_params(adev);
3815#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303816 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3817 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003818 if (adev->visualizer_start_output != NULL)
3819 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3820 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303821 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003822 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003823 }
Derek Chenf13dd492018-11-13 14:53:51 -08003824
3825 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
3826 /* Update cached volume from media to offload/direct stream */
3827 struct listnode *node = NULL;
3828 list_for_each(node, &adev->active_outputs_list) {
3829 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3830 streams_output_ctxt_t,
3831 list);
3832 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3833 out->volume_l = out_ctxt->output->volume_l;
3834 out->volume_r = out_ctxt->output->volume_r;
3835 }
3836 }
3837 out_set_compr_volume(&out->stream,
3838 out->volume_l, out->volume_r);
3839 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003840 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003841
3842 if (ret == 0) {
3843 register_out_stream(out);
3844 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003845 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3846 ALOGE("%s: pcm stream not ready", __func__);
3847 goto error_open;
3848 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003849 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003850 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003851 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003852 if (ret < 0)
3853 goto error_open;
3854 }
3855 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003856 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303857 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003858 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003859
vivek mehtad15d2bf2019-05-17 13:35:10 -07003860 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3861 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3862 audio_low_latency_hint_start();
3863 }
3864
Manish Dewangan21a850a2017-08-14 12:03:55 +05303865 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003866 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003867 if (ret < 0)
3868 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3869 }
3870
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003871 // consider a scenario where on pause lower layers are tear down.
3872 // so on resume, swap mixer control need to be sent only when
3873 // backend is active, hence rather than sending from enable device
3874 // sending it from start of streamtream
3875
3876 platform_set_swap_channels(adev, true);
3877
Haynes Mathew George380745d2017-10-04 15:27:45 -07003878 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303879 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003880 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003881error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003882 if (adev->haptic_pcm) {
3883 pcm_close(adev->haptic_pcm);
3884 adev->haptic_pcm = NULL;
3885 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003886 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303887 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003888 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003889error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303890 /*
3891 * sleep 50ms to allow sufficient time for kernel
3892 * drivers to recover incases like SSR.
3893 */
3894 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003895 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303896 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003897 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003898}
3899
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003900static int check_input_parameters(uint32_t sample_rate,
3901 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003902 int channel_count,
3903 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003904{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003905 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003906
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303907 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3908 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3909 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003910 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003911 !audio_extn_compr_cap_format_supported(format) &&
3912 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003913 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003914
Aalique Grahame22e49102018-12-18 14:23:57 -08003915 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3916 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3917 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3918 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3919 return -EINVAL;
3920 }
3921
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003922 switch (channel_count) {
3923 case 1:
3924 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303925 case 3:
3926 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003927 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003928 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303929 case 10:
3930 case 12:
3931 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003932 break;
3933 default:
3934 ret = -EINVAL;
3935 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003936
3937 switch (sample_rate) {
3938 case 8000:
3939 case 11025:
3940 case 12000:
3941 case 16000:
3942 case 22050:
3943 case 24000:
3944 case 32000:
3945 case 44100:
3946 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003947 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303948 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003949 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303950 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951 break;
3952 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003953 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 }
3955
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003956 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957}
3958
Naresh Tanniru04f71882018-06-26 17:46:22 +05303959
3960/** Add a value in a list if not already present.
3961 * @return true if value was successfully inserted or already present,
3962 * false if the list is full and does not contain the value.
3963 */
3964static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3965 for (size_t i = 0; i < list_length; i++) {
3966 if (list[i] == value) return true; // value is already present
3967 if (list[i] == 0) { // no values in this slot
3968 list[i] = value;
3969 return true; // value inserted
3970 }
3971 }
3972 return false; // could not insert value
3973}
3974
3975/** Add channel_mask in supported_channel_masks if not already present.
3976 * @return true if channel_mask was successfully inserted or already present,
3977 * false if supported_channel_masks is full and does not contain channel_mask.
3978 */
3979static void register_channel_mask(audio_channel_mask_t channel_mask,
3980 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3981 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3982 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3983}
3984
3985/** Add format in supported_formats if not already present.
3986 * @return true if format was successfully inserted or already present,
3987 * false if supported_formats is full and does not contain format.
3988 */
3989static void register_format(audio_format_t format,
3990 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3991 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3992 "%s: stream can not declare supporting its format %x", __func__, format);
3993}
3994/** Add sample_rate in supported_sample_rates if not already present.
3995 * @return true if sample_rate was successfully inserted or already present,
3996 * false if supported_sample_rates is full and does not contain sample_rate.
3997 */
3998static void register_sample_rate(uint32_t sample_rate,
3999 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
4000 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
4001 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
4002}
4003
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004004static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4005{
4006 uint32_t high = num1, low = num2, temp = 0;
4007
4008 if (!num1 || !num2)
4009 return 0;
4010
4011 if (num1 < num2) {
4012 high = num2;
4013 low = num1;
4014 }
4015
4016 while (low != 0) {
4017 temp = low;
4018 low = high % low;
4019 high = temp;
4020 }
4021 return (num1 * num2)/high;
4022}
4023
4024static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4025{
4026 uint32_t remainder = 0;
4027
4028 if (!multiplier)
4029 return num;
4030
4031 remainder = num % multiplier;
4032 if (remainder)
4033 num += (multiplier - remainder);
4034
4035 return num;
4036}
4037
Aalique Grahame22e49102018-12-18 14:23:57 -08004038static size_t get_stream_buffer_size(size_t duration_ms,
4039 uint32_t sample_rate,
4040 audio_format_t format,
4041 int channel_count,
4042 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004043{
4044 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004045 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004046
Aalique Grahame22e49102018-12-18 14:23:57 -08004047 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004048 if (is_low_latency)
4049 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304050
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004051 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004052 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004053
Ralf Herzbd08d632018-09-28 15:50:49 +02004054 /* make sure the size is multiple of 32 bytes and additionally multiple of
4055 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004056 * At 48 kHz mono 16-bit PCM:
4057 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4058 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004059 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004060 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004061 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004062
4063 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064}
4065
Aalique Grahame22e49102018-12-18 14:23:57 -08004066static size_t get_input_buffer_size(uint32_t sample_rate,
4067 audio_format_t format,
4068 int channel_count,
4069 bool is_low_latency)
4070{
4071 /* Don't know if USB HIFI in this context so use true to be conservative */
4072 if (check_input_parameters(sample_rate, format, channel_count,
4073 true /*is_usb_hifi */) != 0)
4074 return 0;
4075
4076 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4077 sample_rate,
4078 format,
4079 channel_count,
4080 is_low_latency);
4081}
4082
Derek Chenf6318be2017-06-12 17:16:24 -04004083size_t get_output_period_size(uint32_t sample_rate,
4084 audio_format_t format,
4085 int channel_count,
4086 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304087{
4088 size_t size = 0;
4089 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4090
4091 if ((duration == 0) || (sample_rate == 0) ||
4092 (bytes_per_sample == 0) || (channel_count == 0)) {
4093 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4094 bytes_per_sample, channel_count);
4095 return -EINVAL;
4096 }
4097
4098 size = (sample_rate *
4099 duration *
4100 bytes_per_sample *
4101 channel_count) / 1000;
4102 /*
4103 * To have same PCM samples for all channels, the buffer size requires to
4104 * be multiple of (number of channels * bytes per sample)
4105 * For writes to succeed, the buffer must be written at address which is multiple of 32
4106 */
4107 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4108
4109 return (size/(channel_count * bytes_per_sample));
4110}
4111
Zhou Song48453a02018-01-10 17:50:59 +08004112static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304113{
4114 uint64_t actual_frames_rendered = 0;
4115 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4116
4117 /* This adjustment accounts for buffering after app processor.
4118 * It is based on estimated DSP latency per use case, rather than exact.
4119 */
4120 int64_t platform_latency = platform_render_latency(out->usecase) *
4121 out->sample_rate / 1000000LL;
4122
Zhou Song48453a02018-01-10 17:50:59 +08004123 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304124 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4125 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4126 * hence only estimate.
4127 */
4128 int64_t signed_frames = out->written - kernel_buffer_size;
4129
4130 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
4131
Zhou Song48453a02018-01-10 17:50:59 +08004132 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304133 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004134 if (timestamp != NULL )
4135 *timestamp = out->writeAt;
4136 } else if (timestamp != NULL) {
4137 clock_gettime(CLOCK_MONOTONIC, timestamp);
4138 }
4139 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304140
4141 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
4142 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
4143 (long long int)out->written, (int)kernel_buffer_size,
4144 audio_bytes_per_sample(out->compr_config.codec->format),
4145 popcount(out->channel_mask));
4146
4147 return actual_frames_rendered;
4148}
4149
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4151{
4152 struct stream_out *out = (struct stream_out *)stream;
4153
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004154 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004155}
4156
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004157static int out_set_sample_rate(struct audio_stream *stream __unused,
4158 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004159{
4160 return -ENOSYS;
4161}
4162
4163static size_t out_get_buffer_size(const struct audio_stream *stream)
4164{
4165 struct stream_out *out = (struct stream_out *)stream;
4166
Varun Balaraje49253e2017-07-06 19:48:56 +05304167 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304168 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304169 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304170 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4171 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4172 else
4173 return out->compr_config.fragment_size;
4174 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004175 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304176 else if (is_offload_usecase(out->usecase) &&
4177 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304178 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004179
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004180 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004181 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004182}
4183
4184static uint32_t out_get_channels(const struct audio_stream *stream)
4185{
4186 struct stream_out *out = (struct stream_out *)stream;
4187
4188 return out->channel_mask;
4189}
4190
4191static audio_format_t out_get_format(const struct audio_stream *stream)
4192{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004193 struct stream_out *out = (struct stream_out *)stream;
4194
4195 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004196}
4197
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004198static int out_set_format(struct audio_stream *stream __unused,
4199 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004200{
4201 return -ENOSYS;
4202}
4203
4204static int out_standby(struct audio_stream *stream)
4205{
4206 struct stream_out *out = (struct stream_out *)stream;
4207 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004208 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004209
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304210 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4211 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004213 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004214 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004215 if (adev->adm_deregister_stream)
4216 adev->adm_deregister_stream(adev->adm_data, out->handle);
4217
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004218 if (is_offload_usecase(out->usecase))
4219 stop_compressed_output_l(out);
4220
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004221 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004222 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004223 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4224 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304225 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004226 pthread_mutex_unlock(&adev->lock);
4227 pthread_mutex_unlock(&out->lock);
4228 ALOGD("VOIP output entered standby");
4229 return 0;
4230 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004231 if (out->pcm) {
4232 pcm_close(out->pcm);
4233 out->pcm = NULL;
4234 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004235 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4236 do_stop = out->playback_started;
4237 out->playback_started = false;
4238 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004239 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004240 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304241 out->send_next_track_params = false;
4242 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004243 out->gapless_mdata.encoder_delay = 0;
4244 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004245 if (out->compr != NULL) {
4246 compress_close(out->compr);
4247 out->compr = NULL;
4248 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004249 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004250 if (do_stop) {
4251 stop_output_stream(out);
4252 }
Lakshman Chaluvaraju40459022019-06-24 10:04:52 +05304253 // if fm is active route on selected device in UI
4254 audio_extn_fm_route_on_selected_device(adev, out->devices);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004255 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004256 }
4257 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304258 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004259 return 0;
4260}
4261
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304262static int out_on_error(struct audio_stream *stream)
4263{
4264 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004265 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304266
4267 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004268 // always send CMD_ERROR for offload streams, this
4269 // is needed e.g. when SSR happens within compress_open
4270 // since the stream is active, offload_callback_thread is also active.
4271 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4272 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004273 }
4274 pthread_mutex_unlock(&out->lock);
4275
4276 status = out_standby(&out->stream.common);
4277
4278 lock_output_stream(out);
4279 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004280 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304281 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304282
4283 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4284 ALOGD("Setting previous card status if offline");
4285 out->prev_card_status_offline = true;
4286 }
4287
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304288 pthread_mutex_unlock(&out->lock);
4289
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004290 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304291}
4292
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304293/*
4294 *standby implementation without locks, assumes that the callee already
4295 *has taken adev and out lock.
4296 */
4297int out_standby_l(struct audio_stream *stream)
4298{
4299 struct stream_out *out = (struct stream_out *)stream;
4300 struct audio_device *adev = out->dev;
4301
4302 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4303 stream, out->usecase, use_case_table[out->usecase]);
4304
4305 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004306 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304307 if (adev->adm_deregister_stream)
4308 adev->adm_deregister_stream(adev->adm_data, out->handle);
4309
4310 if (is_offload_usecase(out->usecase))
4311 stop_compressed_output_l(out);
4312
4313 out->standby = true;
4314 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4315 voice_extn_compress_voip_close_output_stream(stream);
4316 out->started = 0;
4317 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004318 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304319 return 0;
4320 } else if (!is_offload_usecase(out->usecase)) {
4321 if (out->pcm) {
4322 pcm_close(out->pcm);
4323 out->pcm = NULL;
4324 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004325 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4326 if (adev->haptic_pcm) {
4327 pcm_close(adev->haptic_pcm);
4328 adev->haptic_pcm = NULL;
4329 }
4330
4331 if (adev->haptic_buffer != NULL) {
4332 free(adev->haptic_buffer);
4333 adev->haptic_buffer = NULL;
4334 adev->haptic_buffer_size = 0;
4335 }
4336 adev->haptic_pcm_device_id = 0;
4337 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304338 } else {
4339 ALOGD("copl(%p):standby", out);
4340 out->send_next_track_params = false;
4341 out->is_compr_metadata_avail = false;
4342 out->gapless_mdata.encoder_delay = 0;
4343 out->gapless_mdata.encoder_padding = 0;
4344 if (out->compr != NULL) {
4345 compress_close(out->compr);
4346 out->compr = NULL;
4347 }
4348 }
4349 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004350 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304351 }
4352 ALOGD("%s: exit", __func__);
4353 return 0;
4354}
4355
Aalique Grahame22e49102018-12-18 14:23:57 -08004356static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004357{
Aalique Grahame22e49102018-12-18 14:23:57 -08004358 struct stream_out *out = (struct stream_out *)stream;
4359
4360 // We try to get the lock for consistency,
4361 // but it isn't necessary for these variables.
4362 // If we're not in standby, we may be blocked on a write.
4363 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4364 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4365 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4366
4367 if (locked) {
4368 pthread_mutex_unlock(&out->lock);
4369 }
4370
4371 // dump error info
4372 (void)error_log_dump(
4373 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375 return 0;
4376}
4377
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004378static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4379{
4380 int ret = 0;
4381 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004382
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004383 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004384 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004385 return -EINVAL;
4386 }
4387
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304388 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004389
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004390 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4391 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304392 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004393 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004394 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4395 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304396 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004397 }
4398
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004399 ALOGV("%s new encoder delay %u and padding %u", __func__,
4400 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4401
4402 return 0;
4403}
4404
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004405static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4406{
4407 return out == adev->primary_output || out == adev->voice_tx_output;
4408}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004409
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304410// note: this call is safe only if the stream_cb is
4411// removed first in close_output_stream (as is done now).
4412static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4413{
4414 if (!stream || !parms)
4415 return;
4416
4417 struct stream_out *out = (struct stream_out *)stream;
4418 struct audio_device *adev = out->dev;
4419
4420 card_status_t status;
4421 int card;
4422 if (parse_snd_card_status(parms, &card, &status) < 0)
4423 return;
4424
4425 pthread_mutex_lock(&adev->lock);
4426 bool valid_cb = (card == adev->snd_card);
4427 pthread_mutex_unlock(&adev->lock);
4428
4429 if (!valid_cb)
4430 return;
4431
4432 lock_output_stream(out);
4433 if (out->card_status != status)
4434 out->card_status = status;
4435 pthread_mutex_unlock(&out->lock);
4436
4437 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4438 use_case_table[out->usecase],
4439 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4440
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304441 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304442 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304443 if (voice_is_call_state_active(adev) &&
4444 out == adev->primary_output) {
4445 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4446 pthread_mutex_lock(&adev->lock);
4447 voice_stop_call(adev);
4448 adev->mode = AUDIO_MODE_NORMAL;
4449 pthread_mutex_unlock(&adev->lock);
4450 }
4451 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304452 return;
4453}
4454
Kevin Rocardfce19002017-08-07 19:21:36 -07004455static int get_alive_usb_card(struct str_parms* parms) {
4456 int card;
4457 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4458 !audio_extn_usb_alive(card)) {
4459 return card;
4460 }
4461 return -ENODEV;
4462}
4463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004464static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4465{
4466 struct stream_out *out = (struct stream_out *)stream;
4467 struct audio_device *adev = out->dev;
4468 struct str_parms *parms;
4469 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004470 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304471 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004472 bool reconfig = false;
4473 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004474
sangwoobc677242013-08-08 16:53:43 +09004475 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004476 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304478 if (!parms)
4479 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004480 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4481 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004482 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004483 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004484 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004485
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004486 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004487 * When HDMI cable is unplugged the music playback is paused and
4488 * the policy manager sends routing=0. But the audioflinger continues
4489 * to write data until standby time (3sec). As the HDMI core is
4490 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004491 * Avoid this by routing audio to speaker until standby.
4492 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004493 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4494 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304495 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004496 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4497 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004498 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304499 /*
4500 * When A2DP is disconnected the
4501 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004502 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304503 * (3sec). As BT is turned off, the write gets blocked.
4504 * Avoid this by routing audio to speaker until standby.
4505 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004506 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004507 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004508 !audio_extn_a2dp_source_is_ready() &&
4509 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304510 val = AUDIO_DEVICE_OUT_SPEAKER;
4511 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304512 /*
4513 * When USB headset is disconnected the music platback paused
4514 * and the policy manager send routing=0. But if the USB is connected
4515 * back before the standby time, AFE is not closed and opened
4516 * when USB is connected back. So routing to speker will guarantee
4517 * AFE reconfiguration and AFE will be opend once USB is connected again
4518 */
4519 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4520 (val == AUDIO_DEVICE_NONE) &&
4521 !audio_extn_usb_connected(parms)) {
4522 val = AUDIO_DEVICE_OUT_SPEAKER;
4523 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304524 /* To avoid a2dp to sco overlapping / BT device improper state
4525 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304526 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304527 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004528 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004529 if (val &
4530 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304531 //combo usecase just by pass a2dp
4532 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304533 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304534 } else {
4535 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4536 /* update device to a2dp and don't route as BT returned error
4537 * However it is still possible a2dp routing called because
4538 * of current active device disconnection (like wired headset)
4539 */
4540 out->devices = val;
4541 pthread_mutex_unlock(&out->lock);
4542 pthread_mutex_unlock(&adev->lock);
4543 goto error;
4544 }
4545 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304546 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004547
4548 audio_devices_t new_dev = val;
4549
4550 // Workaround: If routing to an non existing usb device, fail gracefully
4551 // The routing request will otherwise block during 10 second
4552 int card;
4553 if (audio_is_usb_out_device(new_dev) &&
4554 (card = get_alive_usb_card(parms)) >= 0) {
4555
4556 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4557 pthread_mutex_unlock(&adev->lock);
4558 pthread_mutex_unlock(&out->lock);
4559 ret = -ENOSYS;
4560 goto routing_fail;
4561 }
4562
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004563 /*
4564 * select_devices() call below switches all the usecases on the same
4565 * backend to the new device. Refer to check_usecases_codec_backend() in
4566 * the select_devices(). But how do we undo this?
4567 *
4568 * For example, music playback is active on headset (deep-buffer usecase)
4569 * and if we go to ringtones and select a ringtone, low-latency usecase
4570 * will be started on headset+speaker. As we can't enable headset+speaker
4571 * and headset devices at the same time, select_devices() switches the music
4572 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4573 * So when the ringtone playback is completed, how do we undo the same?
4574 *
4575 * We are relying on the out_set_parameters() call on deep-buffer output,
4576 * once the ringtone playback is ended.
4577 * NOTE: We should not check if the current devices are same as new devices.
4578 * Because select_devices() must be called to switch back the music
4579 * playback to headset.
4580 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004581 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004582 audio_devices_t new_dev = val;
4583 bool same_dev = out->devices == new_dev;
4584 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004585
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004586 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004587 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004588 if (adev->mode == AUDIO_MODE_IN_CALL) {
4589 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004590 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4591 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4592 audio_extn_usb_set_service_interval(true /*playback*/,
4593 service_interval,
4594 &reconfig);
4595 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4596 }
4597 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004598 }
4599 } else {
4600 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004601 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004602 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004603 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004604
4605 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004606 if (!same_dev) {
4607 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304608 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4609 adev->perf_lock_opts,
4610 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004611 if (adev->adm_on_routing_change)
4612 adev->adm_on_routing_change(adev->adm_data,
4613 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004614 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304615 if (!bypass_a2dp) {
4616 select_devices(adev, out->usecase);
4617 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004618 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4619 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4620 else
4621 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304622 select_devices(adev, out->usecase);
4623 out->devices = new_dev;
4624 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004625
4626 if (!same_dev) {
4627 // on device switch force swap, lower functions will make sure
4628 // to check if swap is allowed or not.
4629 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304630 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004631 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304632 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4633 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004634 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304635 pthread_mutex_lock(&out->compr_mute_lock);
4636 out->a2dp_compress_mute = false;
4637 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4638 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004639 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4640 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304641 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004642 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004643 }
4644
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004646 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004647
4648 /*handles device and call state changes*/
4649 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004650 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004651 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004652
4653 if (out == adev->primary_output) {
4654 pthread_mutex_lock(&adev->lock);
4655 audio_extn_set_parameters(adev, parms);
4656 pthread_mutex_unlock(&adev->lock);
4657 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004658 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004659 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004660 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004661
4662 audio_extn_dts_create_state_notifier_node(out->usecase);
4663 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4664 popcount(out->channel_mask),
4665 out->playback_started);
4666
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004667 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004668 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004669
Surendar Karkaf51b5842018-04-26 11:28:38 +05304670 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4671 sizeof(value));
4672 if (err >= 0) {
4673 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4674 audio_extn_send_dual_mono_mixing_coefficients(out);
4675 }
4676
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304677 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4678 if (err >= 0) {
4679 strlcpy(out->profile, value, sizeof(out->profile));
4680 ALOGV("updating stream profile with value '%s'", out->profile);
4681 lock_output_stream(out);
4682 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4683 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004684 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304685 out->sample_rate, out->bit_width,
4686 out->channel_mask, out->profile,
4687 &out->app_type_cfg);
4688 pthread_mutex_unlock(&out->lock);
4689 }
4690
Alexy Joseph98988832017-01-13 14:56:59 -08004691 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004692 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4693 // and vendor.audio.hal.output.suspend.supported is set to true
4694 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004695 //check suspend parameter only for low latency and if the property
4696 //is enabled
4697 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4698 ALOGI("%s: got suspend_playback %s", __func__, value);
4699 lock_output_stream(out);
4700 if (!strncmp(value, "false", 5)) {
4701 //suspend_playback=false is supposed to set QOS value back to 75%
4702 //the mixer control sent with value Enable will achieve that
4703 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4704 } else if (!strncmp (value, "true", 4)) {
4705 //suspend_playback=true is supposed to remove QOS value
4706 //resetting the mixer control will set the default value
4707 //for the mixer control which is Disable and this removes the QOS vote
4708 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4709 } else {
4710 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4711 " got %s", __func__, value);
4712 ret = -1;
4713 }
4714
4715 if (ret != 0) {
4716 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4717 __func__, out->pm_qos_mixer_path, ret);
4718 }
4719
4720 pthread_mutex_unlock(&out->lock);
4721 }
4722 }
4723 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004724 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304725error:
Eric Laurent994a6932013-07-17 11:51:42 -07004726 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004727 return ret;
4728}
4729
Paul McLeana50b7332018-12-17 08:24:21 -07004730static int in_set_microphone_direction(const struct audio_stream_in *stream,
4731 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004732 struct stream_in *in = (struct stream_in *)stream;
4733
4734 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4735
4736 in->direction = dir;
4737
4738 if (in->standby)
4739 return 0;
4740
4741 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004742}
4743
4744static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004745 struct stream_in *in = (struct stream_in *)stream;
4746
4747 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4748
4749 if (zoom > 1.0 || zoom < -1.0)
4750 return -EINVAL;
4751
4752 in->zoom = zoom;
4753
4754 if (in->standby)
4755 return 0;
4756
4757 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004758}
4759
4760
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004761static bool stream_get_parameter_channels(struct str_parms *query,
4762 struct str_parms *reply,
4763 audio_channel_mask_t *supported_channel_masks) {
4764 int ret = -1;
4765 char value[512];
4766 bool first = true;
4767 size_t i, j;
4768
4769 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4770 ret = 0;
4771 value[0] = '\0';
4772 i = 0;
4773 while (supported_channel_masks[i] != 0) {
4774 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4775 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4776 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304777 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004778
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304779 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004780 first = false;
4781 break;
4782 }
4783 }
4784 i++;
4785 }
4786 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4787 }
4788 return ret == 0;
4789}
4790
4791static bool stream_get_parameter_formats(struct str_parms *query,
4792 struct str_parms *reply,
4793 audio_format_t *supported_formats) {
4794 int ret = -1;
4795 char value[256];
4796 size_t i, j;
4797 bool first = true;
4798
4799 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4800 ret = 0;
4801 value[0] = '\0';
4802 i = 0;
4803 while (supported_formats[i] != 0) {
4804 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4805 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4806 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304807 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004808 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304809 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004810 first = false;
4811 break;
4812 }
4813 }
4814 i++;
4815 }
4816 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4817 }
4818 return ret == 0;
4819}
4820
4821static bool stream_get_parameter_rates(struct str_parms *query,
4822 struct str_parms *reply,
4823 uint32_t *supported_sample_rates) {
4824
4825 int i;
4826 char value[256];
4827 int ret = -1;
4828 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4829 ret = 0;
4830 value[0] = '\0';
4831 i=0;
4832 int cursor = 0;
4833 while (supported_sample_rates[i]) {
4834 int avail = sizeof(value) - cursor;
4835 ret = snprintf(value + cursor, avail, "%s%d",
4836 cursor > 0 ? "|" : "",
4837 supported_sample_rates[i]);
4838 if (ret < 0 || ret >= avail) {
4839 // if cursor is at the last element of the array
4840 // overwrite with \0 is duplicate work as
4841 // snprintf already put a \0 in place.
4842 // else
4843 // we had space to write the '|' at value[cursor]
4844 // (which will be overwritten) or no space to fill
4845 // the first element (=> cursor == 0)
4846 value[cursor] = '\0';
4847 break;
4848 }
4849 cursor += ret;
4850 ++i;
4851 }
4852 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4853 value);
4854 }
4855 return ret >= 0;
4856}
4857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4859{
4860 struct stream_out *out = (struct stream_out *)stream;
4861 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004862 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004863 char value[256];
4864 struct str_parms *reply = str_parms_create();
4865 size_t i, j;
4866 int ret;
4867 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004868
4869 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004870 if (reply) {
4871 str_parms_destroy(reply);
4872 }
4873 if (query) {
4874 str_parms_destroy(query);
4875 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004876 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4877 return NULL;
4878 }
4879
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004880 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004881 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4882 if (ret >= 0) {
4883 value[0] = '\0';
4884 i = 0;
4885 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004886 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4887 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004888 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004889 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004890 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004891 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004892 first = false;
4893 break;
4894 }
4895 }
4896 i++;
4897 }
4898 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4899 str = str_parms_to_str(reply);
4900 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004901 voice_extn_out_get_parameters(out, query, reply);
4902 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004903 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004904
Alexy Joseph62142aa2015-11-16 15:10:34 -08004905
4906 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4907 if (ret >= 0) {
4908 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304909 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4910 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004911 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304912 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004913 } else {
4914 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304915 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004916 }
4917 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004918 if (str)
4919 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004920 str = str_parms_to_str(reply);
4921 }
4922
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004923 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4924 if (ret >= 0) {
4925 value[0] = '\0';
4926 i = 0;
4927 first = true;
4928 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004929 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4930 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004931 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004932 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004933 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004934 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004935 first = false;
4936 break;
4937 }
4938 }
4939 i++;
4940 }
4941 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004942 if (str)
4943 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004944 str = str_parms_to_str(reply);
4945 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004946
4947 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4948 if (ret >= 0) {
4949 value[0] = '\0';
4950 i = 0;
4951 first = true;
4952 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004953 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4954 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004955 if (!first) {
4956 strlcat(value, "|", sizeof(value));
4957 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004958 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004959 first = false;
4960 break;
4961 }
4962 }
4963 i++;
4964 }
4965 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4966 if (str)
4967 free(str);
4968 str = str_parms_to_str(reply);
4969 }
4970
Alexy Joseph98988832017-01-13 14:56:59 -08004971 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4972 //only low latency track supports suspend_resume
4973 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004974 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004975 if (str)
4976 free(str);
4977 str = str_parms_to_str(reply);
4978 }
4979
4980
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004981 str_parms_destroy(query);
4982 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004983 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004984 return str;
4985}
4986
4987static uint32_t out_get_latency(const struct audio_stream_out *stream)
4988{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004989 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004990 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004991 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004992
Alexy Josephaa54c872014-12-03 02:46:47 -08004993 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304994 lock_output_stream(out);
4995 latency = audio_extn_utils_compress_get_dsp_latency(out);
4996 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004997 } else if ((out->realtime) ||
4998 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004999 // since the buffer won't be filled up faster than realtime,
5000 // return a smaller number
5001 if (out->config.rate)
5002 period_ms = (out->af_period_multiplier * out->config.period_size *
5003 1000) / (out->config.rate);
5004 else
5005 period_ms = 0;
5006 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005007 } else {
5008 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005009 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005010 }
5011
yidongh0515e042017-07-06 15:00:34 +08005012 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005013 latency += audio_extn_a2dp_get_encoder_latency();
5014
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305015 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005016 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005017}
5018
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305019static float AmpToDb(float amplification)
5020{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305021 float db = DSD_VOLUME_MIN_DB;
5022 if (amplification > 0) {
5023 db = 20 * log10(amplification);
5024 if(db < DSD_VOLUME_MIN_DB)
5025 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305026 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305027 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305028}
5029
Arun Mirpuri5d170872019-03-26 13:21:31 -07005030static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5031 float right)
5032{
5033 struct stream_out *out = (struct stream_out *)stream;
5034 long volume = 0;
5035 char mixer_ctl_name[128] = "";
5036 struct audio_device *adev = out->dev;
5037 struct mixer_ctl *ctl = NULL;
5038 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5039 PCM_PLAYBACK);
5040
5041 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5042 "Playback %d Volume", pcm_device_id);
5043 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5044 if (!ctl) {
5045 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5046 __func__, mixer_ctl_name);
5047 return -EINVAL;
5048 }
5049 if (left != right)
5050 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5051 __func__, left, right);
5052 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5053 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5054 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5055 __func__, mixer_ctl_name, volume);
5056 return -EINVAL;
5057 }
5058 return 0;
5059}
5060
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305061static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5062 float right)
5063{
5064 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305065 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305066 char mixer_ctl_name[128];
5067 struct audio_device *adev = out->dev;
5068 struct mixer_ctl *ctl;
5069 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5070 PCM_PLAYBACK);
5071
5072 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5073 "Compress Playback %d Volume", pcm_device_id);
5074 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5075 if (!ctl) {
5076 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5077 __func__, mixer_ctl_name);
5078 return -EINVAL;
5079 }
5080 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5081 __func__, mixer_ctl_name, left, right);
5082 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5083 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5084 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5085
5086 return 0;
5087}
5088
Zhou Song2b8f28f2017-09-11 10:51:38 +08005089static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5090 float right)
5091{
5092 struct stream_out *out = (struct stream_out *)stream;
5093 char mixer_ctl_name[] = "App Type Gain";
5094 struct audio_device *adev = out->dev;
5095 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305096 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005097
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005098 if (!is_valid_volume(left, right)) {
5099 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5100 __func__, left, right);
5101 return -EINVAL;
5102 }
5103
Zhou Song2b8f28f2017-09-11 10:51:38 +08005104 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5105 if (!ctl) {
5106 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5107 __func__, mixer_ctl_name);
5108 return -EINVAL;
5109 }
5110
5111 set_values[0] = 0; //0: Rx Session 1:Tx Session
5112 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305113 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5114 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005115
5116 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5117 return 0;
5118}
5119
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305120static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5121 float right)
5122{
5123 struct stream_out *out = (struct stream_out *)stream;
5124 /* Volume control for pcm playback */
5125 if (left != right) {
5126 return -EINVAL;
5127 } else {
5128 char mixer_ctl_name[128];
5129 struct audio_device *adev = out->dev;
5130 struct mixer_ctl *ctl;
5131 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5132 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5133 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5134 if (!ctl) {
5135 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5136 return -EINVAL;
5137 }
5138
5139 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5140 int ret = mixer_ctl_set_value(ctl, 0, volume);
5141 if (ret < 0) {
5142 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5143 return -EINVAL;
5144 }
5145
5146 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5147
5148 return 0;
5149 }
5150}
5151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005152static int out_set_volume(struct audio_stream_out *stream, float left,
5153 float right)
5154{
Eric Laurenta9024de2013-04-04 09:19:12 -07005155 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005156 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305157 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005158
Arun Mirpuri5d170872019-03-26 13:21:31 -07005159 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005160 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5161 /* only take left channel into account: the API is for stereo anyway */
5162 out->muted = (left == 0.0f);
5163 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005164 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305165 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005166 /*
5167 * Set mute or umute on HDMI passthrough stream.
5168 * Only take left channel into account.
5169 * Mute is 0 and unmute 1
5170 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305171 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305172 } else if (out->format == AUDIO_FORMAT_DSD){
5173 char mixer_ctl_name[128] = "DSD Volume";
5174 struct audio_device *adev = out->dev;
5175 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5176
5177 if (!ctl) {
5178 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5179 __func__, mixer_ctl_name);
5180 return -EINVAL;
5181 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305182 volume[0] = (long)(AmpToDb(left));
5183 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305184 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5185 return 0;
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005186 } else if ((out->devices & AUDIO_DEVICE_OUT_BUS) &&
5187 (audio_extn_auto_hal_get_snd_device_for_car_audio_stream(out) ==
5188 SND_DEVICE_OUT_BUS_MEDIA)) {
5189 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5190 struct listnode *node = NULL;
5191 list_for_each(node, &adev->active_outputs_list) {
5192 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5193 streams_output_ctxt_t,
5194 list);
5195 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5196 out->volume_l = out_ctxt->output->volume_l;
5197 out->volume_r = out_ctxt->output->volume_r;
5198 }
5199 }
5200 if (!out->a2dp_compress_mute) {
5201 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5202 }
5203 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005204 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305205 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005206 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305207 if (!out->a2dp_compress_mute)
5208 ret = out_set_compr_volume(stream, left, right);
5209 out->volume_l = left;
5210 out->volume_r = right;
5211 pthread_mutex_unlock(&out->compr_mute_lock);
5212 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005213 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005214 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005215 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5216 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5217 if (!out->standby) {
5218 audio_extn_utils_send_app_type_gain(out->dev,
5219 out->app_type_cfg.app_type,
5220 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005221 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005222 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005223 out->volume_l = left;
5224 out->volume_r = right;
5225 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005226 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5227 ALOGV("%s: MMAP set volume called", __func__);
5228 if (!out->standby)
5229 ret = out_set_mmap_volume(stream, left, right);
5230 out->volume_l = left;
5231 out->volume_r = right;
5232 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305233 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305234 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5235 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305236 /* Volume control for pcm playback */
5237 if (!out->standby)
5238 ret = out_set_pcm_volume(stream, left, right);
5239 else
5240 out->apply_volume = true;
5241
5242 out->volume_l = left;
5243 out->volume_r = right;
5244 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005245 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5246 ALOGV("%s: bus device set volume called", __func__);
5247 if (!out->standby)
5248 ret = out_set_pcm_volume(stream, left, right);
5249 out->volume_l = left;
5250 out->volume_r = right;
5251 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005252 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005253
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005254 return -ENOSYS;
5255}
5256
Zhou Songc9672822017-08-16 16:01:39 +08005257static void update_frames_written(struct stream_out *out, size_t bytes)
5258{
5259 size_t bpf = 0;
5260
5261 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5262 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5263 bpf = 1;
5264 else if (!is_offload_usecase(out->usecase))
5265 bpf = audio_bytes_per_sample(out->format) *
5266 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005267
5268 pthread_mutex_lock(&out->position_query_lock);
5269 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005270 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005271 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5272 }
5273 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005274}
5275
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005276int split_and_write_audio_haptic_data(struct stream_out *out,
5277 const void *buffer, size_t bytes_to_write)
5278{
5279 struct audio_device *adev = out->dev;
5280
5281 int ret = 0;
5282 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5283 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5284 size_t frame_size = channel_count * bytes_per_sample;
5285 size_t frame_count = bytes_to_write / frame_size;
5286
5287 bool force_haptic_path =
5288 property_get_bool("vendor.audio.test_haptic", false);
5289
5290 // extract Haptics data from Audio buffer
5291 bool alloc_haptic_buffer = false;
5292 int haptic_channel_count = adev->haptics_config.channels;
5293 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5294 size_t audio_frame_size = frame_size - haptic_frame_size;
5295 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5296
5297 if (adev->haptic_buffer == NULL) {
5298 alloc_haptic_buffer = true;
5299 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5300 free(adev->haptic_buffer);
5301 adev->haptic_buffer_size = 0;
5302 alloc_haptic_buffer = true;
5303 }
5304
5305 if (alloc_haptic_buffer) {
5306 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005307 if(adev->haptic_buffer == NULL) {
5308 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5309 return -ENOMEM;
5310 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005311 adev->haptic_buffer_size = total_haptic_buffer_size;
5312 }
5313
5314 size_t src_index = 0, aud_index = 0, hap_index = 0;
5315 uint8_t *audio_buffer = (uint8_t *)buffer;
5316 uint8_t *haptic_buffer = adev->haptic_buffer;
5317
5318 // This is required for testing only. This works for stereo data only.
5319 // One channel is fed to audio stream and other to haptic stream for testing.
5320 if (force_haptic_path)
5321 audio_frame_size = haptic_frame_size = bytes_per_sample;
5322
5323 for (size_t i = 0; i < frame_count; i++) {
5324 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5325 audio_frame_size);
5326 aud_index += audio_frame_size;
5327 src_index += audio_frame_size;
5328
5329 if (adev->haptic_pcm)
5330 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5331 haptic_frame_size);
5332 hap_index += haptic_frame_size;
5333 src_index += haptic_frame_size;
5334
5335 // This is required for testing only.
5336 // Discard haptic channel data.
5337 if (force_haptic_path)
5338 src_index += haptic_frame_size;
5339 }
5340
5341 // write to audio pipeline
5342 ret = pcm_write(out->pcm, (void *)audio_buffer,
5343 frame_count * audio_frame_size);
5344
5345 // write to haptics pipeline
5346 if (adev->haptic_pcm)
5347 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5348 frame_count * haptic_frame_size);
5349
5350 return ret;
5351}
5352
Aalique Grahame22e49102018-12-18 14:23:57 -08005353#ifdef NO_AUDIO_OUT
5354static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5355 const void *buffer __unused, size_t bytes)
5356{
5357 struct stream_out *out = (struct stream_out *)stream;
5358
5359 /* No Output device supported other than BT for playback.
5360 * Sleep for the amount of buffer duration
5361 */
5362 lock_output_stream(out);
5363 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5364 (const struct audio_stream_out *)&out->stream) /
5365 out_get_sample_rate(&out->stream.common));
5366 pthread_mutex_unlock(&out->lock);
5367 return bytes;
5368}
5369#endif
5370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005371static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5372 size_t bytes)
5373{
5374 struct stream_out *out = (struct stream_out *)stream;
5375 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005376 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305377 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005378 const size_t frame_size = audio_stream_out_frame_size(stream);
5379 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305380 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005381
Haynes Mathew George380745d2017-10-04 15:27:45 -07005382 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005383 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305384
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305385 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005386
Dhananjay Kumarac341582017-02-23 23:42:25 +05305387 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305388 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305389 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5390 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005391 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305392 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305393 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305394 ALOGD(" %s: sound card is not active/SSR state", __func__);
5395 ret= -EIO;
5396 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305397 }
5398 }
5399
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305400 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305401 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305402 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305403 goto exit;
5404 }
5405
Haynes Mathew George16081042017-05-31 17:16:49 -07005406 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5407 ret = -EINVAL;
5408 goto exit;
5409 }
5410
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305411 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5412 !out->is_iec61937_info_available) {
5413
5414 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5415 out->is_iec61937_info_available = true;
5416 } else if (audio_extn_passthru_is_enabled()) {
5417 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305418 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305419
5420 if((out->format == AUDIO_FORMAT_DTS) ||
5421 (out->format == AUDIO_FORMAT_DTS_HD)) {
5422 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5423 buffer, bytes);
5424 if (ret) {
5425 if (ret != -ENOSYS) {
5426 out->is_iec61937_info_available = false;
5427 ALOGD("iec61937 transmission info not yet updated retry");
5428 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305429 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305430 /* if stream has started and after that there is
5431 * stream config change (iec transmission config)
5432 * then trigger select_device to update backend configuration.
5433 */
5434 out->stream_config_changed = true;
5435 pthread_mutex_lock(&adev->lock);
5436 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305437 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005438 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305439 ret = -EINVAL;
5440 goto exit;
5441 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305442 pthread_mutex_unlock(&adev->lock);
5443 out->stream_config_changed = false;
5444 out->is_iec61937_info_available = true;
5445 }
5446 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305447
Garmond Leung317cbf12017-09-13 16:20:50 -07005448 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305449 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5450 (out->is_iec61937_info_available == true)) {
5451 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5452 ret = -EINVAL;
5453 goto exit;
5454 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305455 }
5456 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305457
5458 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005459 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005460 if (!(out->devices &
5461 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305462 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305463 ret = -EIO;
5464 goto exit;
5465 }
5466 }
5467 }
5468
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005469 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005470 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005471 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005472 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5473 ret = voice_extn_compress_voip_start_output_stream(out);
5474 else
5475 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005476 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005477 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005478 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005479 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005480 goto exit;
5481 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305482 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005483 if (last_known_cal_step != -1) {
5484 ALOGD("%s: retry previous failed cal level set", __func__);
5485 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305486 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005487 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305488
5489 if ((out->is_iec61937_info_available == true) &&
5490 (audio_extn_passthru_is_passthrough_stream(out))&&
5491 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5492 ret = -EINVAL;
5493 goto exit;
5494 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305495 if (out->set_dual_mono)
5496 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005497 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005498
Ashish Jain81eb2a82015-05-13 10:52:34 +05305499 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005500 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305501 adev->is_channel_status_set = true;
5502 }
5503
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305504 if ((adev->use_old_pspd_mix_ctrl == true) &&
5505 (out->pspd_coeff_sent == false)) {
5506 /*
5507 * Need to resend pspd coefficients after stream started for
5508 * older kernel version as it does not save the coefficients
5509 * and also stream has to be started for coeff to apply.
5510 */
5511 usecase = get_usecase_from_list(adev, out->usecase);
5512 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305513 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305514 out->pspd_coeff_sent = true;
5515 }
5516 }
5517
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005518 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005519 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005520 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005521 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005522 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5523 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305524 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5525 ALOGD("copl(%p):send next track params in gapless", out);
Weiyin Jiangebfa0502019-07-18 17:24:21 +08005526 compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305527 out->send_next_track_params = false;
5528 out->is_compr_metadata_avail = false;
5529 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005530 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305531 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305532 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005533
Ashish Jain83a6cc22016-06-28 14:34:17 +05305534 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305535 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305536 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305537 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005538 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305539 return -EINVAL;
5540 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305541 audio_format_t dst_format = out->hal_op_format;
5542 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305543
Dieter Luecking5d57def2018-09-07 14:23:37 +02005544 /* prevent division-by-zero */
5545 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5546 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5547 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5548 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305549 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005550 ATRACE_END();
5551 return -EINVAL;
5552 }
5553
Ashish Jainf1eaa582016-05-23 20:54:24 +05305554 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5555 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5556
Ashish Jain83a6cc22016-06-28 14:34:17 +05305557 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305558 dst_format,
5559 buffer,
5560 src_format,
5561 frames);
5562
Ashish Jain83a6cc22016-06-28 14:34:17 +05305563 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305564 bytes_to_write);
5565
5566 /*Convert written bytes in audio flinger format*/
5567 if (ret > 0)
5568 ret = ((ret * format_to_bitwidth_table[out->format]) /
5569 format_to_bitwidth_table[dst_format]);
5570 }
5571 } else
5572 ret = compress_write(out->compr, buffer, bytes);
5573
Zhou Songc9672822017-08-16 16:01:39 +08005574 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5575 update_frames_written(out, bytes);
5576
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305577 if (ret < 0)
5578 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005579 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305580 /*msg to cb thread only if non blocking write is enabled*/
5581 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305582 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005583 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305584 } else if (-ENETRESET == ret) {
5585 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305586 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305587 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305588 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005589 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305590 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005591 }
Ashish Jain5106d362016-05-11 19:23:33 +05305592
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305593 /* Call compr start only when non-zero bytes of data is there to be rendered */
5594 if (!out->playback_started && ret > 0) {
5595 int status = compress_start(out->compr);
5596 if (status < 0) {
5597 ret = status;
5598 ALOGE("%s: compr start failed with err %d", __func__, errno);
5599 goto exit;
5600 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005601 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005602 out->playback_started = 1;
5603 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005604
5605 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5606 popcount(out->channel_mask),
5607 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005608 }
5609 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005610 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005611 return ret;
5612 } else {
5613 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005614 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005615 if (out->muted)
5616 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005617 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5618 __func__, frames, frame_size, bytes_to_write);
5619
Aalique Grahame22e49102018-12-18 14:23:57 -08005620 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005621 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5622 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5623 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005624 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5625 int16_t *src = (int16_t *)buffer;
5626 int16_t *dst = (int16_t *)buffer;
5627
5628 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5629 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005630 "out_write called for %s use case with wrong properties",
5631 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005632
5633 /*
5634 * FIXME: this can be removed once audio flinger mixer supports
5635 * mono output
5636 */
5637
5638 /*
5639 * Code below goes over each frame in the buffer and adds both
5640 * L and R samples and then divides by 2 to convert to mono
5641 */
5642 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5643 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5644 }
5645 bytes_to_write /= 2;
5646 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005647
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305648 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005649
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005650 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005651
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005652 if (out->config.rate)
5653 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5654 out->config.rate;
5655
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005656 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005657 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5658
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005659 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005660 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005661 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305662 out->convert_buffer != NULL) {
5663
5664 memcpy_by_audio_format(out->convert_buffer,
5665 out->hal_op_format,
5666 buffer,
5667 out->hal_ip_format,
5668 out->config.period_size * out->config.channels);
5669
5670 ret = pcm_write(out->pcm, out->convert_buffer,
5671 (out->config.period_size *
5672 out->config.channels *
5673 format_to_bitwidth_table[out->hal_op_format]));
5674 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305675 /*
5676 * To avoid underrun in DSP when the application is not pumping
5677 * data at required rate, check for the no. of bytes and ignore
5678 * pcm_write if it is less than actual buffer size.
5679 * It is a work around to a change in compress VOIP driver.
5680 */
5681 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5682 bytes < (out->config.period_size * out->config.channels *
5683 audio_bytes_per_sample(out->format))) {
5684 size_t voip_buf_size =
5685 out->config.period_size * out->config.channels *
5686 audio_bytes_per_sample(out->format);
5687 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5688 __func__, bytes, voip_buf_size);
5689 usleep(((uint64_t)voip_buf_size - bytes) *
5690 1000000 / audio_stream_out_frame_size(stream) /
5691 out_get_sample_rate(&out->stream.common));
5692 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005693 } else {
5694 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5695 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5696 else
5697 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5698 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305699 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005700
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005701 release_out_focus(out);
5702
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305703 if (ret < 0)
5704 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005705 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305706 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005707 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005708 }
5709
5710exit:
Zhou Songc9672822017-08-16 16:01:39 +08005711 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305712 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305713 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305714 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005715 pthread_mutex_unlock(&out->lock);
5716
5717 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005718 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005719 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305720 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305721 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305722 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305723 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305724 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305725 out->standby = true;
5726 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305727 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005728 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5729 /* prevent division-by-zero */
5730 uint32_t stream_size = audio_stream_out_frame_size(stream);
5731 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005732
Dieter Luecking5d57def2018-09-07 14:23:37 +02005733 if ((stream_size == 0) || (srate == 0)) {
5734 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5735 ATRACE_END();
5736 return -EINVAL;
5737 }
5738 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5739 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005740 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305741 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005742 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005743 return ret;
5744 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005745 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005746 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005747 return bytes;
5748}
5749
5750static int out_get_render_position(const struct audio_stream_out *stream,
5751 uint32_t *dsp_frames)
5752{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005753 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005754
5755 if (dsp_frames == NULL)
5756 return -EINVAL;
5757
5758 *dsp_frames = 0;
5759 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005760 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305761
5762 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5763 * this operation and adev_close_output_stream(where out gets reset).
5764 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305765 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005766 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305767 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005768 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305769 return 0;
5770 }
5771
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005772 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305773 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305774 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005775 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305776 if (ret < 0)
5777 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005778 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305779 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005780 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305781 if (-ENETRESET == ret) {
5782 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305783 out->card_status = CARD_STATUS_OFFLINE;
5784 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305785 } else if(ret < 0) {
5786 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305787 ret = -EINVAL;
5788 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305789 /*
5790 * Handle corner case where compress session is closed during SSR
5791 * and timestamp is queried
5792 */
5793 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305794 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305795 } else if (out->prev_card_status_offline) {
5796 ALOGE("ERROR: previously sound card was offline,return error");
5797 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305798 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305799 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005800 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305801 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305802 pthread_mutex_unlock(&out->lock);
5803 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005804 } else if (audio_is_linear_pcm(out->format)) {
5805 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005806 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005807 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005808 } else
5809 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005810}
5811
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005812static int out_add_audio_effect(const struct audio_stream *stream __unused,
5813 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005814{
5815 return 0;
5816}
5817
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005818static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5819 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005820{
5821 return 0;
5822}
5823
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005824static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5825 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005826{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305827 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005828}
5829
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005830static int out_get_presentation_position(const struct audio_stream_out *stream,
5831 uint64_t *frames, struct timespec *timestamp)
5832{
5833 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305834 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005835 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005836
Ashish Jain5106d362016-05-11 19:23:33 +05305837 /* below piece of code is not guarded against any lock because audioFliner serializes
5838 * this operation and adev_close_output_stream( where out gets reset).
5839 */
5840 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305841 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005842 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305843 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5844 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5845 return 0;
5846 }
5847
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005848 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005849
Ashish Jain5106d362016-05-11 19:23:33 +05305850 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5851 ret = compress_get_tstamp(out->compr, &dsp_frames,
5852 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005853 // Adjustment accounts for A2dp encoder latency with offload usecases
5854 // Note: Encoder latency is returned in ms.
5855 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5856 unsigned long offset =
5857 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5858 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5859 }
Ashish Jain5106d362016-05-11 19:23:33 +05305860 ALOGVV("%s rendered frames %ld sample_rate %d",
5861 __func__, dsp_frames, out->sample_rate);
5862 *frames = dsp_frames;
5863 if (ret < 0)
5864 ret = -errno;
5865 if (-ENETRESET == ret) {
5866 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305867 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305868 ret = -EINVAL;
5869 } else
5870 ret = 0;
5871 /* this is the best we can do */
5872 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005873 } else {
5874 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005875 unsigned int avail;
5876 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5877 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5878 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5879 // This adjustment accounts for buffering after app processor.
5880 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005881 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005882 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005883
Weiyin Jiangd4633762018-03-16 12:05:03 +08005884 // Adjustment accounts for A2dp encoder latency with non offload usecases
5885 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5886 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5887 signed_frames -=
5888 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5889 }
5890
5891 // It would be unusual for this value to be negative, but check just in case ...
5892 if (signed_frames >= 0) {
5893 *frames = signed_frames;
5894 ret = 0;
5895 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005896 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305897 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305898 *frames = out->written;
5899 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305900 if (is_offload_usecase(out->usecase))
5901 ret = -EINVAL;
5902 else
5903 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005904 }
5905 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005906 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005907 return ret;
5908}
5909
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005910static int out_set_callback(struct audio_stream_out *stream,
5911 stream_callback_t callback, void *cookie)
5912{
5913 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005914 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005915
5916 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005917 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005918 out->client_callback = callback;
5919 out->client_cookie = cookie;
5920 if (out->adsp_hdlr_stream_handle) {
5921 ret = audio_extn_adsp_hdlr_stream_set_callback(
5922 out->adsp_hdlr_stream_handle,
5923 callback,
5924 cookie);
5925 if (ret)
5926 ALOGW("%s:adsp hdlr callback registration failed %d",
5927 __func__, ret);
5928 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005929 pthread_mutex_unlock(&out->lock);
5930 return 0;
5931}
5932
5933static int out_pause(struct audio_stream_out* stream)
5934{
5935 struct stream_out *out = (struct stream_out *)stream;
5936 int status = -ENOSYS;
5937 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005938 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005939 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005940 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005941 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305942 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305943 status = compress_pause(out->compr);
5944
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005945 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005946
Mingming Yin21854652016-04-13 11:54:02 -07005947 if (audio_extn_passthru_is_active()) {
5948 ALOGV("offload use case, pause passthru");
5949 audio_extn_passthru_on_pause(out);
5950 }
5951
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305952 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005953 audio_extn_dts_notify_playback_state(out->usecase, 0,
5954 out->sample_rate, popcount(out->channel_mask),
5955 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005956 }
5957 pthread_mutex_unlock(&out->lock);
5958 }
5959 return status;
5960}
5961
5962static int out_resume(struct audio_stream_out* stream)
5963{
5964 struct stream_out *out = (struct stream_out *)stream;
5965 int status = -ENOSYS;
5966 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005967 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005968 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005969 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005970 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005971 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305972 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305973 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005974 }
5975 if (!status) {
5976 out->offload_state = OFFLOAD_STATE_PLAYING;
5977 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305978 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005979 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5980 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005981 }
5982 pthread_mutex_unlock(&out->lock);
5983 }
5984 return status;
5985}
5986
5987static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5988{
5989 struct stream_out *out = (struct stream_out *)stream;
5990 int status = -ENOSYS;
5991 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005992 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005993 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005994 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5995 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5996 else
5997 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5998 pthread_mutex_unlock(&out->lock);
5999 }
6000 return status;
6001}
6002
6003static int out_flush(struct audio_stream_out* stream)
6004{
6005 struct stream_out *out = (struct stream_out *)stream;
6006 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006007 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006008 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006009 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006010 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6011 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006012 } else {
6013 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6014 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006015 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006016 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006017 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006018 return 0;
6019 }
6020 return -ENOSYS;
6021}
6022
Haynes Mathew George16081042017-05-31 17:16:49 -07006023static int out_stop(const struct audio_stream_out* stream)
6024{
6025 struct stream_out *out = (struct stream_out *)stream;
6026 struct audio_device *adev = out->dev;
6027 int ret = -ENOSYS;
6028
6029 ALOGV("%s", __func__);
6030 pthread_mutex_lock(&adev->lock);
6031 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6032 out->playback_started && out->pcm != NULL) {
6033 pcm_stop(out->pcm);
6034 ret = stop_output_stream(out);
6035 out->playback_started = false;
6036 }
6037 pthread_mutex_unlock(&adev->lock);
6038 return ret;
6039}
6040
6041static int out_start(const struct audio_stream_out* stream)
6042{
6043 struct stream_out *out = (struct stream_out *)stream;
6044 struct audio_device *adev = out->dev;
6045 int ret = -ENOSYS;
6046
6047 ALOGV("%s", __func__);
6048 pthread_mutex_lock(&adev->lock);
6049 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6050 !out->playback_started && out->pcm != NULL) {
6051 ret = start_output_stream(out);
6052 if (ret == 0) {
6053 out->playback_started = true;
6054 }
6055 }
6056 pthread_mutex_unlock(&adev->lock);
6057 return ret;
6058}
6059
6060/*
6061 * Modify config->period_count based on min_size_frames
6062 */
6063static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6064{
6065 int periodCountRequested = (min_size_frames + config->period_size - 1)
6066 / config->period_size;
6067 int periodCount = MMAP_PERIOD_COUNT_MIN;
6068
6069 ALOGV("%s original config.period_size = %d config.period_count = %d",
6070 __func__, config->period_size, config->period_count);
6071
6072 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6073 periodCount *= 2;
6074 }
6075 config->period_count = periodCount;
6076
6077 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6078}
6079
Phil Burkfe17efd2019-03-25 10:23:35 -07006080// Read offset for the positional timestamp from a persistent vendor property.
6081// This is to workaround apparent inaccuracies in the timing information that
6082// is used by the AAudio timing model. The inaccuracies can cause glitches.
6083static int64_t get_mmap_out_time_offset() {
6084 const int32_t kDefaultOffsetMicros = 0;
6085 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006086 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006087 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6088 return mmap_time_offset_micros * (int64_t)1000;
6089}
6090
Haynes Mathew George16081042017-05-31 17:16:49 -07006091static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6092 int32_t min_size_frames,
6093 struct audio_mmap_buffer_info *info)
6094{
6095 struct stream_out *out = (struct stream_out *)stream;
6096 struct audio_device *adev = out->dev;
6097 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006098 unsigned int offset1 = 0;
6099 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006100 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006101 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006102 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006103
Arun Mirpuri5d170872019-03-26 13:21:31 -07006104 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306105 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006106 pthread_mutex_lock(&adev->lock);
6107
Sharad Sanglec6f32552018-05-04 16:15:38 +05306108 if (CARD_STATUS_OFFLINE == out->card_status ||
6109 CARD_STATUS_OFFLINE == adev->card_status) {
6110 ALOGW("out->card_status or adev->card_status offline, try again");
6111 ret = -EIO;
6112 goto exit;
6113 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006114 if (info == NULL || min_size_frames == 0) {
6115 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6116 ret = -EINVAL;
6117 goto exit;
6118 }
6119 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6120 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6121 ret = -ENOSYS;
6122 goto exit;
6123 }
6124 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6125 if (out->pcm_device_id < 0) {
6126 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6127 __func__, out->pcm_device_id, out->usecase);
6128 ret = -EINVAL;
6129 goto exit;
6130 }
6131
6132 adjust_mmap_period_count(&out->config, min_size_frames);
6133
Arun Mirpuri5d170872019-03-26 13:21:31 -07006134 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006135 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6136 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6137 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306138 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306139 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6140 out->card_status = CARD_STATUS_OFFLINE;
6141 adev->card_status = CARD_STATUS_OFFLINE;
6142 ret = -EIO;
6143 goto exit;
6144 }
6145
Haynes Mathew George16081042017-05-31 17:16:49 -07006146 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6147 step = "open";
6148 ret = -ENODEV;
6149 goto exit;
6150 }
6151 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6152 if (ret < 0) {
6153 step = "begin";
6154 goto exit;
6155 }
6156 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006157 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006158 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006159 ret = platform_get_mmap_data_fd(adev->platform,
6160 out->pcm_device_id, 0 /*playback*/,
6161 &info->shared_memory_fd,
6162 &mmap_size);
6163 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006164 // Fall back to non exclusive mode
6165 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6166 } else {
6167 if (mmap_size < buffer_size) {
6168 step = "mmap";
6169 goto exit;
6170 }
6171 // FIXME: indicate exclusive mode support by returning a negative buffer size
6172 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006173 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006174 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006175 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006176
6177 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6178 if (ret < 0) {
6179 step = "commit";
6180 goto exit;
6181 }
6182
Phil Burkfe17efd2019-03-25 10:23:35 -07006183 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6184
Haynes Mathew George16081042017-05-31 17:16:49 -07006185 out->standby = false;
6186 ret = 0;
6187
Arun Mirpuri5d170872019-03-26 13:21:31 -07006188 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006189 __func__, info->shared_memory_address, info->buffer_size_frames);
6190
6191exit:
6192 if (ret != 0) {
6193 if (out->pcm == NULL) {
6194 ALOGE("%s: %s - %d", __func__, step, ret);
6195 } else {
6196 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6197 pcm_close(out->pcm);
6198 out->pcm = NULL;
6199 }
6200 }
6201 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306202 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006203 return ret;
6204}
6205
6206static int out_get_mmap_position(const struct audio_stream_out *stream,
6207 struct audio_mmap_position *position)
6208{
6209 struct stream_out *out = (struct stream_out *)stream;
6210 ALOGVV("%s", __func__);
6211 if (position == NULL) {
6212 return -EINVAL;
6213 }
6214 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006215 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006216 return -ENOSYS;
6217 }
6218 if (out->pcm == NULL) {
6219 return -ENOSYS;
6220 }
6221
6222 struct timespec ts = { 0, 0 };
6223 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6224 if (ret < 0) {
6225 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6226 return ret;
6227 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006228 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6229 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006230 return 0;
6231}
6232
6233
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006234/** audio_stream_in implementation **/
6235static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6236{
6237 struct stream_in *in = (struct stream_in *)stream;
6238
6239 return in->config.rate;
6240}
6241
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006242static int in_set_sample_rate(struct audio_stream *stream __unused,
6243 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006244{
6245 return -ENOSYS;
6246}
6247
6248static size_t in_get_buffer_size(const struct audio_stream *stream)
6249{
6250 struct stream_in *in = (struct stream_in *)stream;
6251
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006252 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6253 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006254 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6255 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306256 else if(audio_extn_cin_attached_usecase(in->usecase))
6257 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006258
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006259 return in->config.period_size * in->af_period_multiplier *
6260 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006261}
6262
6263static uint32_t in_get_channels(const struct audio_stream *stream)
6264{
6265 struct stream_in *in = (struct stream_in *)stream;
6266
6267 return in->channel_mask;
6268}
6269
6270static audio_format_t in_get_format(const struct audio_stream *stream)
6271{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006272 struct stream_in *in = (struct stream_in *)stream;
6273
6274 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006275}
6276
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006277static int in_set_format(struct audio_stream *stream __unused,
6278 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006279{
6280 return -ENOSYS;
6281}
6282
6283static int in_standby(struct audio_stream *stream)
6284{
6285 struct stream_in *in = (struct stream_in *)stream;
6286 struct audio_device *adev = in->dev;
6287 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306288 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6289 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006290 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306291
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006292 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006293 if (!in->standby && in->is_st_session) {
6294 ALOGD("%s: sound trigger pcm stop lab", __func__);
6295 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006296 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006297 in->standby = 1;
6298 }
6299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006300 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006301 if (adev->adm_deregister_stream)
6302 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6303
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006304 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006305 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006306 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006307 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006308 voice_extn_compress_voip_close_input_stream(stream);
6309 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006310 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6311 do_stop = in->capture_started;
6312 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006313 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306314 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05306315 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006316 }
6317
Arun Mirpuri5d170872019-03-26 13:21:31 -07006318 if (in->pcm) {
6319 ATRACE_BEGIN("pcm_in_close");
6320 pcm_close(in->pcm);
6321 ATRACE_END();
6322 in->pcm = NULL;
6323 }
6324
Carter Hsu2e429db2019-05-14 18:50:52 +08006325 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Aalique Grahame22e49102018-12-18 14:23:57 -08006326 adev->enable_voicerx = false;
Carter Hsu2e429db2019-05-14 18:50:52 +08006327
6328 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006329 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006330
6331 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6332 adev->num_va_sessions--;
6333
Eric Laurent150dbfe2013-02-27 14:31:02 -08006334 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006335 }
6336 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006337 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006338 return status;
6339}
6340
Aalique Grahame22e49102018-12-18 14:23:57 -08006341static int in_dump(const struct audio_stream *stream,
6342 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006343{
Aalique Grahame22e49102018-12-18 14:23:57 -08006344 struct stream_in *in = (struct stream_in *)stream;
6345
6346 // We try to get the lock for consistency,
6347 // but it isn't necessary for these variables.
6348 // If we're not in standby, we may be blocked on a read.
6349 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6350 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6351 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6352 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6353
6354 if (locked) {
6355 pthread_mutex_unlock(&in->lock);
6356 }
6357
6358 // dump error info
6359 (void)error_log_dump(
6360 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006362 return 0;
6363}
6364
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306365static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6366{
6367 if (!stream || !parms)
6368 return;
6369
6370 struct stream_in *in = (struct stream_in *)stream;
6371 struct audio_device *adev = in->dev;
6372
6373 card_status_t status;
6374 int card;
6375 if (parse_snd_card_status(parms, &card, &status) < 0)
6376 return;
6377
6378 pthread_mutex_lock(&adev->lock);
6379 bool valid_cb = (card == adev->snd_card);
6380 pthread_mutex_unlock(&adev->lock);
6381
6382 if (!valid_cb)
6383 return;
6384
6385 lock_input_stream(in);
6386 if (in->card_status != status)
6387 in->card_status = status;
6388 pthread_mutex_unlock(&in->lock);
6389
6390 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6391 use_case_table[in->usecase],
6392 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6393
6394 // a better solution would be to report error back to AF and let
6395 // it put the stream to standby
6396 if (status == CARD_STATUS_OFFLINE)
6397 in_standby(&in->stream.common);
6398
6399 return;
6400}
6401
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006402static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6403{
6404 struct stream_in *in = (struct stream_in *)stream;
6405 struct audio_device *adev = in->dev;
6406 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006407 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006408 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006409
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306410 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006411 parms = str_parms_create_str(kvpairs);
6412
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306413 if (!parms)
6414 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006415 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006416 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006417
6418 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6419 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006420 val = atoi(value);
6421 /* no audio source uses val == 0 */
6422 if ((in->source != val) && (val != 0)) {
6423 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006424 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6425 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6426 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006427 (in->config.rate == 8000 || in->config.rate == 16000 ||
6428 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006429 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006430 err = voice_extn_compress_voip_open_input_stream(in);
6431 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006432 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006433 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006434 }
6435 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006436 }
6437 }
6438
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006439 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6440 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006441 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006442 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6443
6444 // Workaround: If routing to an non existing usb device, fail gracefully
6445 // The routing request will otherwise block during 10 second
6446 int card;
6447 if (audio_is_usb_in_device(val) &&
6448 (card = get_alive_usb_card(parms)) >= 0) {
6449
6450 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6451 ret = -ENOSYS;
6452 } else {
6453
6454 in->device = val;
6455 /* If recording is in progress, change the tx device to new device */
6456 if (!in->standby && !in->is_st_session) {
6457 ALOGV("update input routing change");
6458 // inform adm before actual routing to prevent glitches.
6459 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006460 adev->adm_on_routing_change(adev->adm_data,
6461 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006462 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006463 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6464 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006465 }
6466 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006467 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006468 }
6469 }
6470
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306471 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6472 if (err >= 0) {
6473 strlcpy(in->profile, value, sizeof(in->profile));
6474 ALOGV("updating stream profile with value '%s'", in->profile);
6475 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6476 &adev->streams_input_cfg_list,
6477 in->device, in->flags, in->format,
6478 in->sample_rate, in->bit_width,
6479 in->profile, &in->app_type_cfg);
6480 }
6481
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006482 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006483 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006484
6485 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306486error:
Eric Laurent994a6932013-07-17 11:51:42 -07006487 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006488 return ret;
6489}
6490
6491static char* in_get_parameters(const struct audio_stream *stream,
6492 const char *keys)
6493{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006494 struct stream_in *in = (struct stream_in *)stream;
6495 struct str_parms *query = str_parms_create_str(keys);
6496 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006497 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006498
6499 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006500 if (reply) {
6501 str_parms_destroy(reply);
6502 }
6503 if (query) {
6504 str_parms_destroy(query);
6505 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006506 ALOGE("in_get_parameters: failed to create query or reply");
6507 return NULL;
6508 }
6509
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006510 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006511
6512 voice_extn_in_get_parameters(in, query, reply);
6513
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006514 stream_get_parameter_channels(query, reply,
6515 &in->supported_channel_masks[0]);
6516 stream_get_parameter_formats(query, reply,
6517 &in->supported_formats[0]);
6518 stream_get_parameter_rates(query, reply,
6519 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006520 str = str_parms_to_str(reply);
6521 str_parms_destroy(query);
6522 str_parms_destroy(reply);
6523
6524 ALOGV("%s: exit: returns - %s", __func__, str);
6525 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006526}
6527
Aalique Grahame22e49102018-12-18 14:23:57 -08006528static int in_set_gain(struct audio_stream_in *stream,
6529 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006530{
Aalique Grahame22e49102018-12-18 14:23:57 -08006531 struct stream_in *in = (struct stream_in *)stream;
6532 char mixer_ctl_name[128];
6533 struct mixer_ctl *ctl;
6534 int ctl_value;
6535
6536 ALOGV("%s: gain %f", __func__, gain);
6537
6538 if (stream == NULL)
6539 return -EINVAL;
6540
6541 /* in_set_gain() only used to silence MMAP capture for now */
6542 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6543 return -ENOSYS;
6544
6545 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6546
6547 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6548 if (!ctl) {
6549 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6550 __func__, mixer_ctl_name);
6551 return -ENOSYS;
6552 }
6553
6554 if (gain < RECORD_GAIN_MIN)
6555 gain = RECORD_GAIN_MIN;
6556 else if (gain > RECORD_GAIN_MAX)
6557 gain = RECORD_GAIN_MAX;
6558 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6559
6560 mixer_ctl_set_value(ctl, 0, ctl_value);
6561
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006562 return 0;
6563}
6564
6565static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6566 size_t bytes)
6567{
6568 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306569
6570 if (in == NULL) {
6571 ALOGE("%s: stream_in ptr is NULL", __func__);
6572 return -EINVAL;
6573 }
6574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006575 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306576 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306577 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006578
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006579 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306580
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006581 if (in->is_st_session) {
6582 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6583 /* Read from sound trigger HAL */
6584 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006585 if (in->standby) {
6586 adev->num_va_sessions++;
6587 in->standby = 0;
6588 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006589 pthread_mutex_unlock(&in->lock);
6590 return bytes;
6591 }
6592
Haynes Mathew George16081042017-05-31 17:16:49 -07006593 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6594 ret = -ENOSYS;
6595 goto exit;
6596 }
6597
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006598 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6599 !in->standby && adev->adm_routing_changed) {
6600 ret = -ENOSYS;
6601 goto exit;
6602 }
6603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006604 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006605 pthread_mutex_lock(&adev->lock);
6606 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6607 ret = voice_extn_compress_voip_start_input_stream(in);
6608 else
6609 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006610 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6611 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006612 pthread_mutex_unlock(&adev->lock);
6613 if (ret != 0) {
6614 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006615 }
6616 in->standby = 0;
6617 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006618
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306619 /* Avoid read if capture_stopped is set */
6620 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6621 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6622 ret = -EINVAL;
6623 goto exit;
6624 }
6625
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006626 // what's the duration requested by the client?
6627 long ns = 0;
6628
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306629 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006630 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6631 in->config.rate;
6632
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006633 ret = request_in_focus(in, ns);
6634 if (ret != 0)
6635 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006636 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006637
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306638 if (audio_extn_cin_attached_usecase(in->usecase)) {
6639 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6640 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306641 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006642 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306643 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006644 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006645 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006646 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006647 } else if (audio_extn_ffv_get_stream() == in) {
6648 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306649 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006650 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306651 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6652 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6653 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6654 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306655 ret = -EINVAL;
6656 goto exit;
6657 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306658 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306659 ret = -errno;
6660 }
6661 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306662 /* bytes read is always set to bytes for non compress usecases */
6663 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006664 }
6665
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006666 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006667
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006668 /*
Quinn Malef6050362019-01-30 15:55:40 -08006669 * Instead of writing zeroes here, we could trust the hardware to always
6670 * provide zeroes when muted. This is also muted with voice recognition
6671 * usecases so that other clients do not have access to voice recognition
6672 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006673 */
Quinn Malef6050362019-01-30 15:55:40 -08006674 if ((ret == 0 && voice_get_mic_mute(adev) &&
6675 !voice_is_in_call_rec_stream(in) &&
6676 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6677 (adev->num_va_sessions &&
6678 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6679 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6680 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006681 memset(buffer, 0, bytes);
6682
6683exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306684 frame_size = audio_stream_in_frame_size(stream);
6685 if (frame_size > 0)
6686 in->frames_read += bytes_read/frame_size;
6687
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006688 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306689 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006690 pthread_mutex_unlock(&in->lock);
6691
6692 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306693 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306694 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306695 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306696 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306697 in->standby = true;
6698 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306699 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6700 bytes_read = bytes;
6701 memset(buffer, 0, bytes);
6702 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006703 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006704 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6705 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006706 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306707 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306708 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006709 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306710 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006711}
6712
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006713static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006714{
6715 return 0;
6716}
6717
Aalique Grahame22e49102018-12-18 14:23:57 -08006718static int in_get_capture_position(const struct audio_stream_in *stream,
6719 int64_t *frames, int64_t *time)
6720{
6721 if (stream == NULL || frames == NULL || time == NULL) {
6722 return -EINVAL;
6723 }
6724 struct stream_in *in = (struct stream_in *)stream;
6725 int ret = -ENOSYS;
6726
6727 lock_input_stream(in);
6728 // note: ST sessions do not close the alsa pcm driver synchronously
6729 // on standby. Therefore, we may return an error even though the
6730 // pcm stream is still opened.
6731 if (in->standby) {
6732 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6733 "%s stream in standby but pcm not NULL for non ST session", __func__);
6734 goto exit;
6735 }
6736 if (in->pcm) {
6737 struct timespec timestamp;
6738 unsigned int avail;
6739 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6740 *frames = in->frames_read + avail;
6741 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6742 ret = 0;
6743 }
6744 }
6745exit:
6746 pthread_mutex_unlock(&in->lock);
6747 return ret;
6748}
6749
Carter Hsu2e429db2019-05-14 18:50:52 +08006750static int in_update_effect_list(bool add, effect_handle_t effect,
6751 struct listnode *head)
6752{
6753 struct listnode *node;
6754 struct in_effect_list *elist = NULL;
6755 struct in_effect_list *target = NULL;
6756 int ret = 0;
6757
6758 if (!head)
6759 return ret;
6760
6761 list_for_each(node, head) {
6762 elist = node_to_item(node, struct in_effect_list, list);
6763 if (elist->handle == effect) {
6764 target = elist;
6765 break;
6766 }
6767 }
6768
6769 if (add) {
6770 if (target) {
6771 ALOGD("effect %p already exist", effect);
6772 return ret;
6773 }
6774
6775 target = (struct in_effect_list *)
6776 calloc(1, sizeof(struct in_effect_list));
6777
6778 if (!target) {
6779 ALOGE("%s:fail to allocate memory", __func__);
6780 return -ENOMEM;
6781 }
6782
6783 target->handle = effect;
6784 list_add_tail(head, &target->list);
6785 } else {
6786 if (target) {
6787 list_remove(&target->list);
6788 free(target);
6789 }
6790 }
6791
6792 return ret;
6793}
6794
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006795static int add_remove_audio_effect(const struct audio_stream *stream,
6796 effect_handle_t effect,
6797 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006798{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006799 struct stream_in *in = (struct stream_in *)stream;
6800 int status = 0;
6801 effect_descriptor_t desc;
6802
6803 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006804 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6805
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006806 if (status != 0)
6807 return status;
6808
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006809 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006810 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006811 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08006812 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
6813 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006814 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08006815
6816 in_update_effect_list(enable, effect, &in->aec_list);
6817 enable = !list_empty(&in->aec_list);
6818 if (enable == in->enable_aec)
6819 goto exit;
6820
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006821 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006822 ALOGD("AEC enable %d", enable);
6823
Aalique Grahame22e49102018-12-18 14:23:57 -08006824 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6825 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6826 in->dev->enable_voicerx = enable;
6827 struct audio_usecase *usecase;
6828 struct listnode *node;
6829 list_for_each(node, &in->dev->usecase_list) {
6830 usecase = node_to_item(node, struct audio_usecase, list);
6831 if (usecase->type == PCM_PLAYBACK)
6832 select_devices(in->dev, usecase->id);
6833 }
6834 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006835 if (!in->standby) {
6836 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6837 select_devices(in->dev, in->usecase);
6838 }
6839
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006840 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006841 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
6842
6843 in_update_effect_list(enable, effect, &in->ns_list);
6844 enable = !list_empty(&in->ns_list);
6845 if (enable == in->enable_ns)
6846 goto exit;
6847
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006848 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006849 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006850 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006851 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6852 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006853 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6854 select_devices(in->dev, in->usecase);
6855 } else
6856 select_devices(in->dev, in->usecase);
6857 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006858 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006859exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006860 pthread_mutex_unlock(&in->dev->lock);
6861 pthread_mutex_unlock(&in->lock);
6862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006863 return 0;
6864}
6865
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006866static int in_add_audio_effect(const struct audio_stream *stream,
6867 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006868{
Eric Laurent994a6932013-07-17 11:51:42 -07006869 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006870 return add_remove_audio_effect(stream, effect, true);
6871}
6872
6873static int in_remove_audio_effect(const struct audio_stream *stream,
6874 effect_handle_t effect)
6875{
Eric Laurent994a6932013-07-17 11:51:42 -07006876 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006877 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006878}
6879
Derek Chenf939fb72018-11-13 13:34:41 -08006880streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6881 audio_io_handle_t input)
6882{
6883 struct listnode *node;
6884
6885 list_for_each(node, &dev->active_inputs_list) {
6886 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6887 streams_input_ctxt_t,
6888 list);
6889 if (in_ctxt->input->capture_handle == input) {
6890 return in_ctxt;
6891 }
6892 }
6893 return NULL;
6894}
6895
6896streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6897 audio_io_handle_t output)
6898{
6899 struct listnode *node;
6900
6901 list_for_each(node, &dev->active_outputs_list) {
6902 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6903 streams_output_ctxt_t,
6904 list);
6905 if (out_ctxt->output->handle == output) {
6906 return out_ctxt;
6907 }
6908 }
6909 return NULL;
6910}
6911
Haynes Mathew George16081042017-05-31 17:16:49 -07006912static int in_stop(const struct audio_stream_in* stream)
6913{
6914 struct stream_in *in = (struct stream_in *)stream;
6915 struct audio_device *adev = in->dev;
6916
6917 int ret = -ENOSYS;
6918 ALOGV("%s", __func__);
6919 pthread_mutex_lock(&adev->lock);
6920 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6921 in->capture_started && in->pcm != NULL) {
6922 pcm_stop(in->pcm);
6923 ret = stop_input_stream(in);
6924 in->capture_started = false;
6925 }
6926 pthread_mutex_unlock(&adev->lock);
6927 return ret;
6928}
6929
6930static int in_start(const struct audio_stream_in* stream)
6931{
6932 struct stream_in *in = (struct stream_in *)stream;
6933 struct audio_device *adev = in->dev;
6934 int ret = -ENOSYS;
6935
6936 ALOGV("%s in %p", __func__, in);
6937 pthread_mutex_lock(&adev->lock);
6938 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6939 !in->capture_started && in->pcm != NULL) {
6940 if (!in->capture_started) {
6941 ret = start_input_stream(in);
6942 if (ret == 0) {
6943 in->capture_started = true;
6944 }
6945 }
6946 }
6947 pthread_mutex_unlock(&adev->lock);
6948 return ret;
6949}
6950
Phil Burke0a86d12019-02-16 22:28:11 -08006951// Read offset for the positional timestamp from a persistent vendor property.
6952// This is to workaround apparent inaccuracies in the timing information that
6953// is used by the AAudio timing model. The inaccuracies can cause glitches.
6954static int64_t in_get_mmap_time_offset() {
6955 const int32_t kDefaultOffsetMicros = 0;
6956 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006957 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006958 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6959 return mmap_time_offset_micros * (int64_t)1000;
6960}
6961
Haynes Mathew George16081042017-05-31 17:16:49 -07006962static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6963 int32_t min_size_frames,
6964 struct audio_mmap_buffer_info *info)
6965{
6966 struct stream_in *in = (struct stream_in *)stream;
6967 struct audio_device *adev = in->dev;
6968 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006969 unsigned int offset1 = 0;
6970 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006971 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006972 uint32_t mmap_size = 0;
6973 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006974
6975 pthread_mutex_lock(&adev->lock);
6976 ALOGV("%s in %p", __func__, in);
6977
Sharad Sanglec6f32552018-05-04 16:15:38 +05306978 if (CARD_STATUS_OFFLINE == in->card_status||
6979 CARD_STATUS_OFFLINE == adev->card_status) {
6980 ALOGW("in->card_status or adev->card_status offline, try again");
6981 ret = -EIO;
6982 goto exit;
6983 }
6984
Haynes Mathew George16081042017-05-31 17:16:49 -07006985 if (info == NULL || min_size_frames == 0) {
6986 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6987 ret = -EINVAL;
6988 goto exit;
6989 }
6990 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6991 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6992 ALOGV("%s in %p", __func__, in);
6993 ret = -ENOSYS;
6994 goto exit;
6995 }
6996 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6997 if (in->pcm_device_id < 0) {
6998 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6999 __func__, in->pcm_device_id, in->usecase);
7000 ret = -EINVAL;
7001 goto exit;
7002 }
7003
7004 adjust_mmap_period_count(&in->config, min_size_frames);
7005
7006 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7007 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7008 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7009 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307010 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307011 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7012 in->card_status = CARD_STATUS_OFFLINE;
7013 adev->card_status = CARD_STATUS_OFFLINE;
7014 ret = -EIO;
7015 goto exit;
7016 }
7017
Haynes Mathew George16081042017-05-31 17:16:49 -07007018 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7019 step = "open";
7020 ret = -ENODEV;
7021 goto exit;
7022 }
7023
7024 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7025 if (ret < 0) {
7026 step = "begin";
7027 goto exit;
7028 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007029
Arun Mirpuri5d170872019-03-26 13:21:31 -07007030 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7031 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7032 info->burst_size_frames = in->config.period_size;
7033 ret = platform_get_mmap_data_fd(adev->platform,
7034 in->pcm_device_id, 1 /*capture*/,
7035 &info->shared_memory_fd,
7036 &mmap_size);
7037 if (ret < 0) {
7038 // Fall back to non exclusive mode
7039 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7040 } else {
7041 if (mmap_size < buffer_size) {
7042 step = "mmap";
7043 goto exit;
7044 }
7045 // FIXME: indicate exclusive mode support by returning a negative buffer size
7046 info->buffer_size_frames *= -1;
7047 }
7048
7049 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007050
7051 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7052 if (ret < 0) {
7053 step = "commit";
7054 goto exit;
7055 }
7056
Phil Burke0a86d12019-02-16 22:28:11 -08007057 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7058
Haynes Mathew George16081042017-05-31 17:16:49 -07007059 in->standby = false;
7060 ret = 0;
7061
7062 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7063 __func__, info->shared_memory_address, info->buffer_size_frames);
7064
7065exit:
7066 if (ret != 0) {
7067 if (in->pcm == NULL) {
7068 ALOGE("%s: %s - %d", __func__, step, ret);
7069 } else {
7070 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7071 pcm_close(in->pcm);
7072 in->pcm = NULL;
7073 }
7074 }
7075 pthread_mutex_unlock(&adev->lock);
7076 return ret;
7077}
7078
7079static int in_get_mmap_position(const struct audio_stream_in *stream,
7080 struct audio_mmap_position *position)
7081{
7082 struct stream_in *in = (struct stream_in *)stream;
7083 ALOGVV("%s", __func__);
7084 if (position == NULL) {
7085 return -EINVAL;
7086 }
7087 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7088 return -ENOSYS;
7089 }
7090 if (in->pcm == NULL) {
7091 return -ENOSYS;
7092 }
7093 struct timespec ts = { 0, 0 };
7094 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7095 if (ret < 0) {
7096 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7097 return ret;
7098 }
Phil Burke0a86d12019-02-16 22:28:11 -08007099 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7100 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007101 return 0;
7102}
7103
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307104static int in_get_active_microphones(const struct audio_stream_in *stream,
7105 struct audio_microphone_characteristic_t *mic_array,
7106 size_t *mic_count) {
7107 struct stream_in *in = (struct stream_in *)stream;
7108 struct audio_device *adev = in->dev;
7109 ALOGVV("%s", __func__);
7110
7111 lock_input_stream(in);
7112 pthread_mutex_lock(&adev->lock);
7113 int ret = platform_get_active_microphones(adev->platform,
7114 audio_channel_count_from_in_mask(in->channel_mask),
7115 in->usecase, mic_array, mic_count);
7116 pthread_mutex_unlock(&adev->lock);
7117 pthread_mutex_unlock(&in->lock);
7118
7119 return ret;
7120}
7121
7122static int adev_get_microphones(const struct audio_hw_device *dev,
7123 struct audio_microphone_characteristic_t *mic_array,
7124 size_t *mic_count) {
7125 struct audio_device *adev = (struct audio_device *)dev;
7126 ALOGVV("%s", __func__);
7127
7128 pthread_mutex_lock(&adev->lock);
7129 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7130 pthread_mutex_unlock(&adev->lock);
7131
7132 return ret;
7133}
juyuchendb308c22019-01-21 11:57:17 -07007134
7135static void in_update_sink_metadata(struct audio_stream_in *stream,
7136 const struct sink_metadata *sink_metadata) {
7137
7138 if (stream == NULL
7139 || sink_metadata == NULL
7140 || sink_metadata->tracks == NULL) {
7141 return;
7142 }
7143
7144 int error = 0;
7145 struct stream_in *in = (struct stream_in *)stream;
7146 struct audio_device *adev = in->dev;
7147 audio_devices_t device = AUDIO_DEVICE_NONE;
7148
7149 if (sink_metadata->track_count != 0)
7150 device = sink_metadata->tracks->dest_device;
7151
7152 lock_input_stream(in);
7153 pthread_mutex_lock(&adev->lock);
7154 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
7155
7156 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
7157 && device != AUDIO_DEVICE_NONE
7158 && adev->voice_tx_output != NULL) {
7159 /* Use the rx device from afe-proxy record to route voice call because
7160 there is no routing if tx device is on primary hal and rx device
7161 is on other hal during voice call. */
7162 adev->voice_tx_output->devices = device;
7163
7164 if (!voice_is_call_state_active(adev)) {
7165 if (adev->mode == AUDIO_MODE_IN_CALL) {
7166 adev->current_call_output = adev->voice_tx_output;
7167 error = voice_start_call(adev);
7168 if (error != 0)
7169 ALOGE("%s: start voice call failed %d", __func__, error);
7170 }
7171 } else {
7172 adev->current_call_output = adev->voice_tx_output;
7173 voice_update_devices_for_all_voice_usecases(adev);
7174 }
7175 }
7176
7177 pthread_mutex_unlock(&adev->lock);
7178 pthread_mutex_unlock(&in->lock);
7179}
7180
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307181int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007182 audio_io_handle_t handle,
7183 audio_devices_t devices,
7184 audio_output_flags_t flags,
7185 struct audio_config *config,
7186 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007187 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007188{
7189 struct audio_device *adev = (struct audio_device *)dev;
7190 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307191 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007192 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007193 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307194 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007195 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7196 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7197 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7198 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007199 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007200 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7201 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007202 bool force_haptic_path =
7203 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007204 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007205
kunleizdff872d2018-08-20 14:40:33 +08007206 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007207 is_usb_dev = false;
7208 devices = AUDIO_DEVICE_OUT_SPEAKER;
7209 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7210 __func__, devices);
7211 }
7212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007213 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307214
Rahul Sharma99770982019-03-06 17:05:26 +05307215 pthread_mutex_lock(&adev->lock);
7216 if (out_get_stream(adev, handle) != NULL) {
7217 ALOGW("%s, output stream already opened", __func__);
7218 ret = -EEXIST;
7219 }
7220 pthread_mutex_unlock(&adev->lock);
7221 if (ret)
7222 return ret;
7223
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007224 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7225
Mingming Yin3a941d42016-02-17 18:08:05 -08007226 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007227 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7228 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307229
7230
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007231 if (!out) {
7232 return -ENOMEM;
7233 }
7234
Haynes Mathew George204045b2015-02-25 20:32:03 -08007235 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007236 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307237 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007238 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007239 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7240
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007241 if (devices == AUDIO_DEVICE_NONE)
7242 devices = AUDIO_DEVICE_OUT_SPEAKER;
7243
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007244 out->flags = flags;
7245 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007246 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007247 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007248 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307249 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307250 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7251 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7252 else
7253 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007254 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007255 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007256 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307257 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307258 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307259 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007260 out->hal_output_suspend_supported = 0;
7261 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307262 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307263 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307264 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007265
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307266 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307267 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007268 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7269
Aalique Grahame22e49102018-12-18 14:23:57 -08007270 if (direct_dev &&
7271 (audio_is_linear_pcm(out->format) ||
7272 config->format == AUDIO_FORMAT_DEFAULT) &&
7273 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7274 audio_format_t req_format = config->format;
7275 audio_channel_mask_t req_channel_mask = config->channel_mask;
7276 uint32_t req_sample_rate = config->sample_rate;
7277
7278 pthread_mutex_lock(&adev->lock);
7279 if (is_hdmi) {
7280 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7281 ret = read_hdmi_sink_caps(out);
7282 if (config->sample_rate == 0)
7283 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7284 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7285 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7286 if (config->format == AUDIO_FORMAT_DEFAULT)
7287 config->format = AUDIO_FORMAT_PCM_16_BIT;
7288 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007289 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7290 &config->format,
7291 &out->supported_formats[0],
7292 MAX_SUPPORTED_FORMATS,
7293 &config->channel_mask,
7294 &out->supported_channel_masks[0],
7295 MAX_SUPPORTED_CHANNEL_MASKS,
7296 &config->sample_rate,
7297 &out->supported_sample_rates[0],
7298 MAX_SUPPORTED_SAMPLE_RATES);
7299 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007300 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007301
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007302 pthread_mutex_unlock(&adev->lock);
7303 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007304 if (ret == -ENOSYS) {
7305 /* ignore and go with default */
7306 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007307 }
7308 // For MMAP NO IRQ, allow conversions in ADSP
7309 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7310 goto error_open;
7311 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007312 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007313 goto error_open;
7314 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007315
7316 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7317 config->sample_rate = req_sample_rate;
7318 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7319 config->channel_mask = req_channel_mask;
7320 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7321 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007322 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007323
7324 out->sample_rate = config->sample_rate;
7325 out->channel_mask = config->channel_mask;
7326 out->format = config->format;
7327 if (is_hdmi) {
7328 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7329 out->config = pcm_config_hdmi_multi;
7330 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7331 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7332 out->config = pcm_config_mmap_playback;
7333 out->stream.start = out_start;
7334 out->stream.stop = out_stop;
7335 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7336 out->stream.get_mmap_position = out_get_mmap_position;
7337 } else {
7338 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7339 out->config = pcm_config_hifi;
7340 }
7341
7342 out->config.rate = out->sample_rate;
7343 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7344 if (is_hdmi) {
7345 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7346 audio_bytes_per_sample(out->format));
7347 }
7348 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007349 }
7350
Derek Chenf6318be2017-06-12 17:16:24 -04007351 /* validate bus device address */
7352 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7353 /* extract car audio stream index */
7354 out->car_audio_stream =
7355 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7356 if (out->car_audio_stream < 0) {
7357 ALOGE("%s: invalid car audio stream %x",
7358 __func__, out->car_audio_stream);
7359 ret = -EINVAL;
7360 goto error_open;
7361 }
7362 /* save car audio stream and address for bus device */
7363 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
7364 ALOGV("%s: address %s, car_audio_stream %x",
7365 __func__, out->address, out->car_audio_stream);
7366 }
7367
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007368 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007369 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007370 if (!voice_extn_is_compress_voip_supported()) {
7371 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7372 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007373 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7374 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007375 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7376 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007377 out->volume_l = INVALID_OUT_VOLUME;
7378 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007379
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007380 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007381 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007382 uint32_t channel_count =
7383 audio_channel_count_from_out_mask(out->channel_mask);
7384 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7385 out->sample_rate, out->format,
7386 channel_count, false);
7387 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7388 if (frame_size != 0)
7389 out->config.period_size = buffer_size / frame_size;
7390 else
7391 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007392 }
7393 } else {
7394 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7395 voice_extn_compress_voip_is_active(out->dev)) &&
7396 (voice_extn_compress_voip_is_config_supported(config))) {
7397 ret = voice_extn_compress_voip_open_output_stream(out);
7398 if (ret != 0) {
7399 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7400 __func__, ret);
7401 goto error_open;
7402 }
Sujin Panickerbd95e0a2019-09-16 18:28:06 +05307403 } else {
7404 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7405 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007406 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007407 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007408 } else if (audio_is_linear_pcm(out->format) &&
7409 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7410 out->channel_mask = config->channel_mask;
7411 out->sample_rate = config->sample_rate;
7412 out->format = config->format;
7413 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7414 // does this change?
7415 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7416 out->config.rate = config->sample_rate;
7417 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7418 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7419 audio_bytes_per_sample(config->format));
7420 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007421 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307422 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307423 pthread_mutex_lock(&adev->lock);
7424 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7425 pthread_mutex_unlock(&adev->lock);
7426
7427 // reject offload during card offline to allow
7428 // fallback to s/w paths
7429 if (offline) {
7430 ret = -ENODEV;
7431 goto error_open;
7432 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007433
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007434 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7435 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7436 ALOGE("%s: Unsupported Offload information", __func__);
7437 ret = -EINVAL;
7438 goto error_open;
7439 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007440
Atul Khare3fa6e542017-08-09 00:56:17 +05307441 if (config->offload_info.format == 0)
7442 config->offload_info.format = config->format;
7443 if (config->offload_info.sample_rate == 0)
7444 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007445
Mingming Yin90310102013-11-13 16:57:00 -08007446 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307447 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007448 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007449 ret = -EINVAL;
7450 goto error_open;
7451 }
7452
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007453 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7454 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7455 (audio_extn_passthru_is_passthrough_stream(out)) &&
7456 !((config->sample_rate == 48000) ||
7457 (config->sample_rate == 96000) ||
7458 (config->sample_rate == 192000))) {
7459 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7460 __func__, config->sample_rate, config->offload_info.format);
7461 ret = -EINVAL;
7462 goto error_open;
7463 }
7464
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007465 out->compr_config.codec = (struct snd_codec *)
7466 calloc(1, sizeof(struct snd_codec));
7467
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007468 if (!out->compr_config.codec) {
7469 ret = -ENOMEM;
7470 goto error_open;
7471 }
7472
Dhananjay Kumarac341582017-02-23 23:42:25 +05307473 out->stream.pause = out_pause;
7474 out->stream.resume = out_resume;
7475 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307476 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307477 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007478 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307479 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007480 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307481 } else {
7482 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7483 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007484 }
vivek mehta446c3962015-09-14 10:57:35 -07007485
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307486 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7487 ALOGD("%s: Setting latency mode to true", __func__);
7488 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
7489 }
7490
vivek mehta446c3962015-09-14 10:57:35 -07007491 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007492 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7493 config->format == 0 && config->sample_rate == 0 &&
7494 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007495 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007496 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7497 } else {
7498 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7499 ret = -EEXIST;
7500 goto error_open;
7501 }
vivek mehta446c3962015-09-14 10:57:35 -07007502 }
7503
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007504 if (config->offload_info.channel_mask)
7505 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007506 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007507 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007508 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007509 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307510 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007511 ret = -EINVAL;
7512 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007513 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007514
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007515 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007516 out->sample_rate = config->offload_info.sample_rate;
7517
Mingming Yin3ee55c62014-08-04 14:23:35 -07007518 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007519
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307520 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307521 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307522 audio_extn_dolby_send_ddp_endp_params(adev);
7523 audio_extn_dolby_set_dmid(adev);
7524 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007525
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007526 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007527 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007528 out->compr_config.codec->bit_rate =
7529 config->offload_info.bit_rate;
7530 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307531 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007532 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307533 /* Update bit width only for non passthrough usecases.
7534 * For passthrough usecases, the output will always be opened @16 bit
7535 */
7536 if (!audio_extn_passthru_is_passthrough_stream(out))
7537 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307538
7539 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7540 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7541 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7542
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007543 /*TODO: Do we need to change it for passthrough */
7544 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007545
Manish Dewangana6fc5442015-08-24 20:30:31 +05307546 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7547 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307548 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307549 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307550 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7551 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307552
7553 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7554 AUDIO_FORMAT_PCM) {
7555
7556 /*Based on platform support, configure appropriate alsa format for corresponding
7557 *hal input format.
7558 */
7559 out->compr_config.codec->format = hal_format_to_alsa(
7560 config->offload_info.format);
7561
Ashish Jain83a6cc22016-06-28 14:34:17 +05307562 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307563 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307564 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307565
Dhananjay Kumarac341582017-02-23 23:42:25 +05307566 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307567 *hal input format and alsa format might differ based on platform support.
7568 */
7569 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307570 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307571
7572 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7573
Deeraj Soman65358ab2019-02-07 15:40:49 +05307574 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7575 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7576 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7577
Ashish Jainf1eaa582016-05-23 20:54:24 +05307578 /* Check if alsa session is configured with the same format as HAL input format,
7579 * if not then derive correct fragment size needed to accomodate the
7580 * conversion of HAL input format to alsa format.
7581 */
7582 audio_extn_utils_update_direct_pcm_fragment_size(out);
7583
7584 /*if hal input and output fragment size is different this indicates HAL input format is
7585 *not same as the alsa format
7586 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307587 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307588 /*Allocate a buffer to convert input data to the alsa configured format.
7589 *size of convert buffer is equal to the size required to hold one fragment size
7590 *worth of pcm data, this is because flinger does not write more than fragment_size
7591 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307592 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7593 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307594 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7595 ret = -ENOMEM;
7596 goto error_open;
7597 }
7598 }
7599 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7600 out->compr_config.fragment_size =
7601 audio_extn_passthru_get_buffer_size(&config->offload_info);
7602 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7603 } else {
7604 out->compr_config.fragment_size =
7605 platform_get_compress_offload_buffer_size(&config->offload_info);
7606 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7607 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007608
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307609 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7610 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7611 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007612 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307613 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007614
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307615 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7616 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7617 }
7618
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007619 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7620 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007621
Manish Dewangan69426c82017-01-30 17:35:36 +05307622 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7623 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7624 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7625 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7626 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7627 } else {
7628 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7629 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007630
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307631 memset(&out->channel_map_param, 0,
7632 sizeof(struct audio_out_channel_map_param));
7633
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007634 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307635 out->send_next_track_params = false;
7636 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007637 out->offload_state = OFFLOAD_STATE_IDLE;
7638 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007639 out->writeAt.tv_sec = 0;
7640 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007641
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007642 audio_extn_dts_create_state_notifier_node(out->usecase);
7643
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007644 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7645 __func__, config->offload_info.version,
7646 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307647
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307648 /* Check if DSD audio format is supported in codec
7649 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307650 */
7651
7652 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307653 (!platform_check_codec_dsd_support(adev->platform) ||
7654 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307655 ret = -EINVAL;
7656 goto error_open;
7657 }
7658
Ashish Jain5106d362016-05-11 19:23:33 +05307659 /* Disable gapless if any of the following is true
7660 * passthrough playback
7661 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307662 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307663 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307664 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307665 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007666 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307667 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307668 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307669 check_and_set_gapless_mode(adev, false);
7670 } else
7671 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007672
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307673 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007674 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7675 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307676 if (config->format == AUDIO_FORMAT_DSD) {
7677 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7678 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7679 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007680
7681 create_offload_callback_thread(out);
7682
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007683 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007684 switch (config->sample_rate) {
7685 case 0:
7686 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7687 break;
7688 case 8000:
7689 case 16000:
7690 case 48000:
7691 out->sample_rate = config->sample_rate;
7692 break;
7693 default:
7694 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7695 config->sample_rate);
7696 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7697 ret = -EINVAL;
7698 goto error_open;
7699 }
7700 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7701 switch (config->channel_mask) {
7702 case AUDIO_CHANNEL_NONE:
7703 case AUDIO_CHANNEL_OUT_STEREO:
7704 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7705 break;
7706 default:
7707 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7708 config->channel_mask);
7709 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7710 ret = -EINVAL;
7711 goto error_open;
7712 }
7713 switch (config->format) {
7714 case AUDIO_FORMAT_DEFAULT:
7715 case AUDIO_FORMAT_PCM_16_BIT:
7716 out->format = AUDIO_FORMAT_PCM_16_BIT;
7717 break;
7718 default:
7719 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7720 config->format);
7721 config->format = AUDIO_FORMAT_PCM_16_BIT;
7722 ret = -EINVAL;
7723 goto error_open;
7724 }
7725
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307726 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007727 if (ret != 0) {
7728 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007729 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007730 goto error_open;
7731 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007732 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007733 switch (config->sample_rate) {
7734 case 0:
7735 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7736 break;
7737 case 8000:
7738 case 16000:
7739 case 48000:
7740 out->sample_rate = config->sample_rate;
7741 break;
7742 default:
7743 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7744 config->sample_rate);
7745 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7746 ret = -EINVAL;
7747 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007748 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007749 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7750 switch (config->channel_mask) {
7751 case AUDIO_CHANNEL_NONE:
7752 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7753 break;
7754 case AUDIO_CHANNEL_OUT_STEREO:
7755 out->channel_mask = config->channel_mask;
7756 break;
7757 default:
7758 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7759 config->channel_mask);
7760 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7761 ret = -EINVAL;
7762 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007763 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007764 switch (config->format) {
7765 case AUDIO_FORMAT_DEFAULT:
7766 out->format = AUDIO_FORMAT_PCM_16_BIT;
7767 break;
7768 case AUDIO_FORMAT_PCM_16_BIT:
7769 out->format = config->format;
7770 break;
7771 default:
7772 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7773 config->format);
7774 config->format = AUDIO_FORMAT_PCM_16_BIT;
7775 ret = -EINVAL;
7776 break;
7777 }
7778 if (ret != 0)
7779 goto error_open;
7780
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007781 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7782 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007783 out->config.rate = out->sample_rate;
7784 out->config.channels =
7785 audio_channel_count_from_out_mask(out->channel_mask);
7786 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007787 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007788 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307789 unsigned int channels = 0;
7790 /*Update config params to default if not set by the caller*/
7791 if (config->sample_rate == 0)
7792 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7793 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7794 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7795 if (config->format == AUDIO_FORMAT_DEFAULT)
7796 config->format = AUDIO_FORMAT_PCM_16_BIT;
7797
7798 channels = audio_channel_count_from_out_mask(out->channel_mask);
7799
Varun Balaraje49253e2017-07-06 19:48:56 +05307800 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7801 out->usecase = get_interactive_usecase(adev);
7802 out->config = pcm_config_low_latency;
7803 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307804 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007805 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7806 out->flags);
7807 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007808 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7809 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7810 out->config = pcm_config_mmap_playback;
7811 out->stream.start = out_start;
7812 out->stream.stop = out_stop;
7813 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7814 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307815 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7816 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007817 out->hal_output_suspend_supported =
7818 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7819 out->dynamic_pm_qos_config_supported =
7820 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7821 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007822 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7823 } else {
7824 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7825 //the mixer path will be a string similar to "low-latency-playback resume"
7826 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7827 strlcat(out->pm_qos_mixer_path,
7828 " resume", MAX_MIXER_PATH_LEN);
7829 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7830 out->pm_qos_mixer_path);
7831 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307832 out->config = pcm_config_low_latency;
7833 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7834 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7835 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307836 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7837 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7838 if (out->config.period_size <= 0) {
7839 ALOGE("Invalid configuration period size is not valid");
7840 ret = -EINVAL;
7841 goto error_open;
7842 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007843 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7844 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7845 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007846 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7847 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7848 out->config = pcm_config_haptics_audio;
7849 if (force_haptic_path)
7850 adev->haptics_config = pcm_config_haptics_audio;
7851 else
7852 adev->haptics_config = pcm_config_haptics;
7853
7854 out->config.channels =
7855 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7856
7857 if (force_haptic_path) {
7858 out->config.channels = 1;
7859 adev->haptics_config.channels = 1;
7860 } else
7861 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Derek Chenf6318be2017-06-12 17:16:24 -04007862 } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7863 ret = audio_extn_auto_hal_open_output_stream(out);
7864 if (ret) {
7865 ALOGE("%s: Failed to open output stream for bus device", __func__);
7866 ret = -EINVAL;
7867 goto error_open;
7868 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307869 } else {
7870 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007871 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7872 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307873 }
7874 out->hal_ip_format = format = out->format;
7875 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7876 out->hal_op_format = pcm_format_to_hal(out->config.format);
7877 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7878 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007879 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307880 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307881 if (out->hal_ip_format != out->hal_op_format) {
7882 uint32_t buffer_size = out->config.period_size *
7883 format_to_bitwidth_table[out->hal_op_format] *
7884 out->config.channels;
7885 out->convert_buffer = calloc(1, buffer_size);
7886 if (out->convert_buffer == NULL){
7887 ALOGE("Allocation failed for convert buffer for size %d",
7888 out->compr_config.fragment_size);
7889 ret = -ENOMEM;
7890 goto error_open;
7891 }
7892 ALOGD("Convert buffer allocated of size %d", buffer_size);
7893 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007894 }
7895
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007896 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7897 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307898
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007899 /* TODO remove this hardcoding and check why width is zero*/
7900 if (out->bit_width == 0)
7901 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307902 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007903 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007904 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307905 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307906 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007907 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007908 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7909 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007910 if(adev->primary_output == NULL)
7911 adev->primary_output = out;
7912 else {
7913 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007914 ret = -EEXIST;
7915 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007916 }
7917 }
7918
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007919 /* Check if this usecase is already existing */
7920 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007921 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7922 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007923 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007924 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007925 ret = -EEXIST;
7926 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007927 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007928
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007929 pthread_mutex_unlock(&adev->lock);
7930
7931 out->stream.common.get_sample_rate = out_get_sample_rate;
7932 out->stream.common.set_sample_rate = out_set_sample_rate;
7933 out->stream.common.get_buffer_size = out_get_buffer_size;
7934 out->stream.common.get_channels = out_get_channels;
7935 out->stream.common.get_format = out_get_format;
7936 out->stream.common.set_format = out_set_format;
7937 out->stream.common.standby = out_standby;
7938 out->stream.common.dump = out_dump;
7939 out->stream.common.set_parameters = out_set_parameters;
7940 out->stream.common.get_parameters = out_get_parameters;
7941 out->stream.common.add_audio_effect = out_add_audio_effect;
7942 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7943 out->stream.get_latency = out_get_latency;
7944 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007945#ifdef NO_AUDIO_OUT
7946 out->stream.write = out_write_for_no_output;
7947#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007948 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007949#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007950 out->stream.get_render_position = out_get_render_position;
7951 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007952 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007953
Haynes Mathew George16081042017-05-31 17:16:49 -07007954 if (out->realtime)
7955 out->af_period_multiplier = af_period_multiplier;
7956 else
7957 out->af_period_multiplier = 1;
7958
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007959 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007960 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007961 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007962
7963 config->format = out->stream.common.get_format(&out->stream.common);
7964 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7965 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307966 register_format(out->format, out->supported_formats);
7967 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7968 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007969
Aalique Grahame22e49102018-12-18 14:23:57 -08007970 out->error_log = error_log_create(
7971 ERROR_LOG_ENTRIES,
7972 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7973
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307974 /*
7975 By locking output stream before registering, we allow the callback
7976 to update stream's state only after stream's initial state is set to
7977 adev state.
7978 */
7979 lock_output_stream(out);
7980 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7981 pthread_mutex_lock(&adev->lock);
7982 out->card_status = adev->card_status;
7983 pthread_mutex_unlock(&adev->lock);
7984 pthread_mutex_unlock(&out->lock);
7985
Aalique Grahame22e49102018-12-18 14:23:57 -08007986 stream_app_type_cfg_init(&out->app_type_cfg);
7987
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007988 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307989 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007990 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007991
7992 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7993 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7994 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007995 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307996 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007997 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007998 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307999 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
8000 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008001 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
8002 out->usecase, PCM_PLAYBACK);
8003 hdlr_stream_cfg.flags = out->flags;
8004 hdlr_stream_cfg.type = PCM_PLAYBACK;
8005 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8006 &hdlr_stream_cfg);
8007 if (ret) {
8008 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8009 out->adsp_hdlr_stream_handle = NULL;
8010 }
8011 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308012 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8013 is_direct_passthough, false);
8014 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8015 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008016 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008017 if (ret < 0) {
8018 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8019 out->ip_hdlr_handle = NULL;
8020 }
8021 }
Derek Chenf939fb72018-11-13 13:34:41 -08008022
8023 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8024 calloc(1, sizeof(streams_output_ctxt_t));
8025 if (out_ctxt == NULL) {
8026 ALOGE("%s fail to allocate output ctxt", __func__);
8027 ret = -ENOMEM;
8028 goto error_open;
8029 }
8030 out_ctxt->output = out;
8031
8032 pthread_mutex_lock(&adev->lock);
8033 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8034 pthread_mutex_unlock(&adev->lock);
8035
Eric Laurent994a6932013-07-17 11:51:42 -07008036 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008037 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008038
8039error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308040 if (out->convert_buffer)
8041 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008042 free(out);
8043 *stream_out = NULL;
8044 ALOGD("%s: exit: ret %d", __func__, ret);
8045 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008046}
8047
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308048void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008049 struct audio_stream_out *stream)
8050{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008051 struct stream_out *out = (struct stream_out *)stream;
8052 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008053 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008054
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008055 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308056
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308057 // must deregister from sndmonitor first to prevent races
8058 // between the callback and close_stream
8059 audio_extn_snd_mon_unregister_listener(out);
8060
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008061 /* close adsp hdrl session before standby */
8062 if (out->adsp_hdlr_stream_handle) {
8063 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8064 if (ret)
8065 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8066 out->adsp_hdlr_stream_handle = NULL;
8067 }
8068
Manish Dewangan21a850a2017-08-14 12:03:55 +05308069 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008070 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8071 out->ip_hdlr_handle = NULL;
8072 }
8073
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008074 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308075 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008076 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308077 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308078 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008079 if(ret != 0)
8080 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8081 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008082 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008083 out_standby(&stream->common);
8084
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008085 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008086 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008087 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008088 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008089 if (out->compr_config.codec != NULL)
8090 free(out->compr_config.codec);
8091 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008092
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308093 out->a2dp_compress_mute = false;
8094
Varun Balaraje49253e2017-07-06 19:48:56 +05308095 if (is_interactive_usecase(out->usecase))
8096 free_interactive_usecase(adev, out->usecase);
8097
Ashish Jain83a6cc22016-06-28 14:34:17 +05308098 if (out->convert_buffer != NULL) {
8099 free(out->convert_buffer);
8100 out->convert_buffer = NULL;
8101 }
8102
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008103 if (adev->voice_tx_output == out)
8104 adev->voice_tx_output = NULL;
8105
Aalique Grahame22e49102018-12-18 14:23:57 -08008106 error_log_destroy(out->error_log);
8107 out->error_log = NULL;
8108
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308109 if (adev->primary_output == out)
8110 adev->primary_output = NULL;
8111
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008112 pthread_cond_destroy(&out->cond);
8113 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008114
8115 pthread_mutex_lock(&adev->lock);
8116 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8117 if (out_ctxt != NULL) {
8118 list_remove(&out_ctxt->list);
8119 free(out_ctxt);
8120 } else {
8121 ALOGW("%s, output stream already closed", __func__);
8122 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008123 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008124 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008125 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008126}
8127
8128static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8129{
8130 struct audio_device *adev = (struct audio_device *)dev;
8131 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008132 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008133 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008134 int ret;
8135 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008136 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008137 struct listnode *node;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008138
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008139 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008140 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008141
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308142 if (!parms)
8143 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308144
Derek Chen6f293672019-04-01 01:40:24 -07008145 /* notify adev and input/output streams on the snd card status */
8146 adev_snd_mon_cb((void *)adev, parms);
8147
8148 list_for_each(node, &adev->active_outputs_list) {
8149 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8150 streams_output_ctxt_t,
8151 list);
8152 out_snd_mon_cb((void *)out_ctxt->output, parms);
8153 }
8154
8155 list_for_each(node, &adev->active_inputs_list) {
8156 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8157 streams_input_ctxt_t,
8158 list);
8159 in_snd_mon_cb((void *)in_ctxt->input, parms);
8160 }
8161
Zhou Songd6d71752019-05-21 18:08:51 +08008162 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308163 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8164 if (ret >= 0) {
8165 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008166 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308167 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008168 } else {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308169 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008170 audio_extn_sco_reset_configuration();
Kunlei Zhang136e6742019-08-27 16:33:29 +08008171 }
8172 }
8173
8174 ret = str_parms_get_str(parms, "A2dpSuspended", value, sizeof(value));
8175 if (ret>=0) {
8176 if (!strncmp(value, "false", 5) &&
8177 audio_extn_a2dp_source_is_suspended()) {
8178 struct audio_usecase *usecase;
8179 struct listnode *node;
Zhou Songd6d71752019-05-21 18:08:51 +08008180 list_for_each(node, &adev->usecase_list) {
8181 usecase = node_to_item(node, struct audio_usecase, list);
Kunlei Zhang136e6742019-08-27 16:33:29 +08008182 if (usecase->stream.in && (usecase->type == PCM_CAPTURE) &&
8183 ((usecase->stream.in->device & ~AUDIO_DEVICE_BIT_IN) &
8184 AUDIO_DEVICE_IN_ALL_SCO)) {
8185 ALOGD("a2dp resumed, switch bt sco mic to handset mic");
Zhou Songd6d71752019-05-21 18:08:51 +08008186 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
Kunlei Zhang136e6742019-08-27 16:33:29 +08008187 select_devices(adev, usecase->id);
8188 }
Zhou Songd6d71752019-05-21 18:08:51 +08008189 }
8190 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308191 }
8192
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008193 status = voice_set_parameters(adev, parms);
8194 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008195 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008196
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008197 status = platform_set_parameters(adev->platform, parms);
8198 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008199 goto done;
8200
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008201 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8202 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008203 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008204 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8205 adev->bluetooth_nrec = true;
8206 else
8207 adev->bluetooth_nrec = false;
8208 }
8209
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008210 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8211 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008212 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8213 adev->screen_off = false;
8214 else
8215 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008216 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008217 }
8218
Eric Laurent4b084132018-10-19 17:33:43 -07008219 ret = str_parms_get_int(parms, "rotation", &val);
8220 if (ret >= 0) {
8221 bool reverse_speakers = false;
8222 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8223 switch (val) {
8224 // FIXME: note that the code below assumes that the speakers are in the correct placement
8225 // relative to the user when the device is rotated 90deg from its default rotation. This
8226 // assumption is device-specific, not platform-specific like this code.
8227 case 270:
8228 reverse_speakers = true;
8229 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8230 break;
8231 case 0:
8232 case 180:
8233 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8234 break;
8235 case 90:
8236 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8237 break;
8238 default:
8239 ALOGE("%s: unexpected rotation of %d", __func__, val);
8240 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008241 }
Eric Laurent4b084132018-10-19 17:33:43 -07008242 if (status == 0) {
8243 // check and set swap
8244 // - check if orientation changed and speaker active
8245 // - set rotation and cache the rotation value
8246 adev->camera_orientation =
8247 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8248 if (!audio_extn_is_maxx_audio_enabled())
8249 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8250 }
8251 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008252
Mingming Yin514a8bc2014-07-29 15:22:21 -07008253 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8254 if (ret >= 0) {
8255 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8256 adev->bt_wb_speech_enabled = true;
8257 else
8258 adev->bt_wb_speech_enabled = false;
8259 }
8260
Zhou Song12c29502019-03-16 10:37:18 +08008261 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8262 if (ret >= 0) {
8263 val = atoi(value);
8264 adev->swb_speech_mode = val;
8265 }
8266
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008267 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8268 if (ret >= 0) {
8269 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308270 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008271 if (audio_is_output_device(val) &&
8272 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008273 ALOGV("cache new ext disp type and edid");
8274 ret = platform_get_ext_disp_type(adev->platform);
8275 if (ret < 0) {
8276 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308277 } else {
8278 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008279 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308280 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008281 /*
8282 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8283 * Per AudioPolicyManager, USB device is higher priority than WFD.
8284 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8285 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8286 * starting voice call on USB
8287 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008288 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308289 if (ret >= 0)
8290 audio_extn_usb_add_device(device, atoi(value));
8291
Zhou Song6f862822017-11-06 17:27:57 +08008292 if (!audio_extn_usb_is_tunnel_supported()) {
8293 ALOGV("detected USB connect .. disable proxy");
8294 adev->allow_afe_proxy_usage = false;
8295 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008296 }
8297 }
8298
8299 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8300 if (ret >= 0) {
8301 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308302 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008303 /*
8304 * The HDMI / Displayport disconnect handling has been moved to
8305 * audio extension to ensure that its parameters are not
8306 * invalidated prior to updating sysfs of the disconnect event
8307 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8308 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308309 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008310 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308311 if (ret >= 0)
8312 audio_extn_usb_remove_device(device, atoi(value));
8313
Zhou Song6f862822017-11-06 17:27:57 +08008314 if (!audio_extn_usb_is_tunnel_supported()) {
8315 ALOGV("detected USB disconnect .. enable proxy");
8316 adev->allow_afe_proxy_usage = true;
8317 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008318 }
8319 }
8320
Aalique Grahame22e49102018-12-18 14:23:57 -08008321 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008322 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008323
8324 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008325 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308326 struct audio_usecase *usecase;
8327 struct listnode *node;
8328 list_for_each(node, &adev->usecase_list) {
8329 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308330 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07008331 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308332 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008333 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308334 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008335 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308336 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308337 ALOGD("Switching to speaker and muting the stream before select_devices");
8338 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308339 //force device switch to re configure encoder
8340 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308341 ALOGD("Unmuting the stream after select_devices");
8342 usecase->stream.out->a2dp_compress_mute = false;
8343 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 +05308344 audio_extn_a2dp_set_handoff_mode(false);
8345 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308346 break;
8347 }
8348 }
8349 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008350
8351 //handle vr audio setparam
8352 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8353 value, sizeof(value));
8354 if (ret >= 0) {
8355 ALOGI("Setting vr mode to be %s", value);
8356 if (!strncmp(value, "true", 4)) {
8357 adev->vr_audio_mode_enabled = true;
8358 ALOGI("Setting vr mode to true");
8359 } else if (!strncmp(value, "false", 5)) {
8360 adev->vr_audio_mode_enabled = false;
8361 ALOGI("Setting vr mode to false");
8362 } else {
8363 ALOGI("wrong vr mode set");
8364 }
8365 }
8366
Eric Laurent4b084132018-10-19 17:33:43 -07008367 //FIXME: to be replaced by proper video capture properties API
8368 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8369 if (ret >= 0) {
8370 int camera_facing = CAMERA_FACING_BACK;
8371 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8372 camera_facing = CAMERA_FACING_FRONT;
8373 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8374 camera_facing = CAMERA_FACING_BACK;
8375 else {
8376 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8377 goto done;
8378 }
8379 adev->camera_orientation =
8380 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8381 struct audio_usecase *usecase;
8382 struct listnode *node;
8383 list_for_each(node, &adev->usecase_list) {
8384 usecase = node_to_item(node, struct audio_usecase, list);
8385 struct stream_in *in = usecase->stream.in;
8386 if (usecase->type == PCM_CAPTURE && in != NULL &&
8387 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8388 select_devices(adev, in->usecase);
8389 }
8390 }
8391 }
8392
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308393 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008394done:
8395 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008396 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308397error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008398 ALOGV("%s: exit with code(%d)", __func__, status);
8399 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008400}
8401
8402static char* adev_get_parameters(const struct audio_hw_device *dev,
8403 const char *keys)
8404{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308405 ALOGD("%s:%s", __func__, keys);
8406
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008407 struct audio_device *adev = (struct audio_device *)dev;
8408 struct str_parms *reply = str_parms_create();
8409 struct str_parms *query = str_parms_create_str(keys);
8410 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308411 char value[256] = {0};
8412 int ret = 0;
8413
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008414 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008415 if (reply) {
8416 str_parms_destroy(reply);
8417 }
8418 if (query) {
8419 str_parms_destroy(query);
8420 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008421 ALOGE("adev_get_parameters: failed to create query or reply");
8422 return NULL;
8423 }
8424
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008425 //handle vr audio getparam
8426
8427 ret = str_parms_get_str(query,
8428 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8429 value, sizeof(value));
8430
8431 if (ret >= 0) {
8432 bool vr_audio_enabled = false;
8433 pthread_mutex_lock(&adev->lock);
8434 vr_audio_enabled = adev->vr_audio_mode_enabled;
8435 pthread_mutex_unlock(&adev->lock);
8436
8437 ALOGI("getting vr mode to %d", vr_audio_enabled);
8438
8439 if (vr_audio_enabled) {
8440 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8441 "true");
8442 goto exit;
8443 } else {
8444 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8445 "false");
8446 goto exit;
8447 }
8448 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008449
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008450 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008451 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008452 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008453 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008454 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308455 pthread_mutex_unlock(&adev->lock);
8456
Naresh Tannirud7205b62014-06-20 02:54:48 +05308457exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008458 str = str_parms_to_str(reply);
8459 str_parms_destroy(query);
8460 str_parms_destroy(reply);
8461
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308462 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008463 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008464}
8465
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008466static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008467{
8468 return 0;
8469}
8470
8471static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8472{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008473 int ret;
8474 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008475
8476 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8477
Haynes Mathew George5191a852013-09-11 14:19:36 -07008478 pthread_mutex_lock(&adev->lock);
8479 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008480 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008481 pthread_mutex_unlock(&adev->lock);
8482 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008483}
8484
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008485static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8486 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008487{
8488 return -ENOSYS;
8489}
8490
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008491static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8492 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008493{
8494 return -ENOSYS;
8495}
8496
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008497static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8498 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008499{
8500 return -ENOSYS;
8501}
8502
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008503static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8504 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008505{
8506 return -ENOSYS;
8507}
8508
8509static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8510{
8511 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008512 struct listnode *node;
8513 struct audio_usecase *usecase = NULL;
8514 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008515
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008516 pthread_mutex_lock(&adev->lock);
8517 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008518 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008519 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008520 if (voice_is_in_call(adev) &&
8521 (mode == AUDIO_MODE_NORMAL ||
8522 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008523 list_for_each(node, &adev->usecase_list) {
8524 usecase = node_to_item(node, struct audio_usecase, list);
8525 if (usecase->type == VOICE_CALL)
8526 break;
8527 }
8528 if (usecase &&
8529 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8530 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8531 true);
8532 if (ret != 0) {
8533 /* default service interval was successfully updated,
8534 reopen USB backend with new service interval */
8535 check_usecases_codec_backend(adev,
8536 usecase,
8537 usecase->out_snd_device);
8538 }
8539 }
8540
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008541 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008542 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008543 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008544 // restore device for other active usecases after stop call
8545 list_for_each(node, &adev->usecase_list) {
8546 usecase = node_to_item(node, struct audio_usecase, list);
8547 select_devices(adev, usecase->id);
8548 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008549 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008550 }
8551 pthread_mutex_unlock(&adev->lock);
8552 return 0;
8553}
8554
8555static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8556{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008557 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008558 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008559
8560 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008561 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008562 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008563
Derek Chend2530072014-11-24 12:39:14 -08008564 if (adev->ext_hw_plugin)
8565 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008566
8567 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008568 pthread_mutex_unlock(&adev->lock);
8569
8570 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008571}
8572
8573static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8574{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008575 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008576 return 0;
8577}
8578
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008579static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008580 const struct audio_config *config)
8581{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008582 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008583
Aalique Grahame22e49102018-12-18 14:23:57 -08008584 /* Don't know if USB HIFI in this context so use true to be conservative */
8585 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8586 true /*is_usb_hifi */) != 0)
8587 return 0;
8588
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008589 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8590 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008591}
8592
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008593static bool adev_input_allow_hifi_record(struct audio_device *adev,
8594 audio_devices_t devices,
8595 audio_input_flags_t flags,
8596 audio_source_t source) {
8597 const bool allowed = true;
8598
8599 if (!audio_is_usb_in_device(devices))
8600 return !allowed;
8601
8602 switch (flags) {
8603 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008604 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008605 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8606 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008607 default:
8608 return !allowed;
8609 }
8610
8611 switch (source) {
8612 case AUDIO_SOURCE_DEFAULT:
8613 case AUDIO_SOURCE_MIC:
8614 case AUDIO_SOURCE_UNPROCESSED:
8615 break;
8616 default:
8617 return !allowed;
8618 }
8619
8620 switch (adev->mode) {
8621 case 0:
8622 break;
8623 default:
8624 return !allowed;
8625 }
8626
8627 return allowed;
8628}
8629
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008630static int adev_update_voice_comm_input_stream(struct stream_in *in,
8631 struct audio_config *config)
8632{
8633 bool valid_rate = (config->sample_rate == 8000 ||
8634 config->sample_rate == 16000 ||
8635 config->sample_rate == 32000 ||
8636 config->sample_rate == 48000);
8637 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8638
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008639 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008640 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008641 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8642 in->config = default_pcm_config_voip_copp;
8643 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8644 DEFAULT_VOIP_BUF_DURATION_MS,
8645 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008646 } else {
8647 ALOGW("%s No valid input in voip, use defaults"
8648 "sample rate %u, channel mask 0x%X",
8649 __func__, config->sample_rate, in->channel_mask);
8650 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008651 in->config.rate = config->sample_rate;
8652 in->sample_rate = config->sample_rate;
8653 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008654 //XXX needed for voice_extn_compress_voip_open_input_stream
8655 in->config.rate = config->sample_rate;
8656 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathacd1de7d2019-08-23 15:13:46 +05308657 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008658 voice_extn_compress_voip_is_active(in->dev)) &&
8659 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8660 valid_rate && valid_ch) {
8661 voice_extn_compress_voip_open_input_stream(in);
8662 // update rate entries to match config from AF
8663 in->config.rate = config->sample_rate;
8664 in->sample_rate = config->sample_rate;
8665 } else {
8666 ALOGW("%s compress voip not active, use defaults", __func__);
8667 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008668 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008669 return 0;
8670}
8671
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008672static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008673 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008674 audio_devices_t devices,
8675 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008676 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308677 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008678 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008679 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008680{
8681 struct audio_device *adev = (struct audio_device *)dev;
8682 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008683 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008684 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008685 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308686 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008687 bool is_usb_dev = audio_is_usb_in_device(devices);
8688 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8689 devices,
8690 flags,
8691 source);
Andy Hung94320602018-10-29 18:31:12 -07008692 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8693 " sample_rate %u, channel_mask %#x, format %#x",
8694 __func__, flags, is_usb_dev, may_use_hifi_record,
8695 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308696
kunleizdff872d2018-08-20 14:40:33 +08008697 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008698 is_usb_dev = false;
8699 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8700 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8701 __func__, devices);
8702 }
8703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008704 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008705
8706 if (!(is_usb_dev && may_use_hifi_record)) {
8707 if (config->sample_rate == 0)
8708 config->sample_rate = 48000;
8709 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8710 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8711 if (config->format == AUDIO_FORMAT_DEFAULT)
8712 config->format = AUDIO_FORMAT_PCM_16_BIT;
8713
8714 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8715
Aalique Grahame22e49102018-12-18 14:23:57 -08008716 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8717 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008718 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308719 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008720
Rahul Sharma99770982019-03-06 17:05:26 +05308721 pthread_mutex_lock(&adev->lock);
8722 if (in_get_stream(adev, handle) != NULL) {
8723 ALOGW("%s, input stream already opened", __func__);
8724 ret = -EEXIST;
8725 }
8726 pthread_mutex_unlock(&adev->lock);
8727 if (ret)
8728 return ret;
8729
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008730 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008731
8732 if (!in) {
8733 ALOGE("failed to allocate input stream");
8734 return -ENOMEM;
8735 }
8736
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308737 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308738 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8739 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008740 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008741 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008742
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008743 in->stream.common.get_sample_rate = in_get_sample_rate;
8744 in->stream.common.set_sample_rate = in_set_sample_rate;
8745 in->stream.common.get_buffer_size = in_get_buffer_size;
8746 in->stream.common.get_channels = in_get_channels;
8747 in->stream.common.get_format = in_get_format;
8748 in->stream.common.set_format = in_set_format;
8749 in->stream.common.standby = in_standby;
8750 in->stream.common.dump = in_dump;
8751 in->stream.common.set_parameters = in_set_parameters;
8752 in->stream.common.get_parameters = in_get_parameters;
8753 in->stream.common.add_audio_effect = in_add_audio_effect;
8754 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8755 in->stream.set_gain = in_set_gain;
8756 in->stream.read = in_read;
8757 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008758 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308759 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008760 in->stream.set_microphone_direction = in_set_microphone_direction;
8761 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008762 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008763
8764 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008765 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008766 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008767 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008768 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008769 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008770 in->bit_width = 16;
8771 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008772 in->direction = MIC_DIRECTION_UNSPECIFIED;
8773 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08008774 list_init(&in->aec_list);
8775 list_init(&in->ns_list);
Haynes Mathew George46740472017-10-27 18:40:12 -07008776
Andy Hung94320602018-10-29 18:31:12 -07008777 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008778 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8779 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8780 /* Force channel config requested to mono if incall
8781 record is being requested for only uplink/downlink */
8782 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8783 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8784 ret = -EINVAL;
8785 goto err_open;
8786 }
8787 }
8788
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008789 if (is_usb_dev && may_use_hifi_record) {
8790 /* HiFi record selects an appropriate format, channel, rate combo
8791 depending on sink capabilities*/
8792 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8793 &config->format,
8794 &in->supported_formats[0],
8795 MAX_SUPPORTED_FORMATS,
8796 &config->channel_mask,
8797 &in->supported_channel_masks[0],
8798 MAX_SUPPORTED_CHANNEL_MASKS,
8799 &config->sample_rate,
8800 &in->supported_sample_rates[0],
8801 MAX_SUPPORTED_SAMPLE_RATES);
8802 if (ret != 0) {
8803 ret = -EINVAL;
8804 goto err_open;
8805 }
8806 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008807 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308808 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308809 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8810 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8811 in->config.format = PCM_FORMAT_S32_LE;
8812 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308813 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8814 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8815 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8816 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8817 bool ret_error = false;
8818 in->bit_width = 24;
8819 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8820 from HAL is 24_packed and 8_24
8821 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8822 24_packed return error indicating supported format is 24_packed
8823 *> In case of any other source requesting 24 bit or float return error
8824 indicating format supported is 16 bit only.
8825
8826 on error flinger will retry with supported format passed
8827 */
8828 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8829 (source != AUDIO_SOURCE_CAMCORDER)) {
8830 config->format = AUDIO_FORMAT_PCM_16_BIT;
8831 if (config->sample_rate > 48000)
8832 config->sample_rate = 48000;
8833 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008834 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8835 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308836 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8837 ret_error = true;
8838 }
8839
8840 if (ret_error) {
8841 ret = -EINVAL;
8842 goto err_open;
8843 }
8844 }
8845
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008846 in->channel_mask = config->channel_mask;
8847 in->format = config->format;
8848
8849 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308850
8851 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8852 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8853 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8854 else {
8855 ret = -EINVAL;
8856 goto err_open;
8857 }
8858 }
8859
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008860 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308861 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
8862 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008863 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8864 is_low_latency = true;
8865#if LOW_LATENCY_CAPTURE_USE_CASE
8866 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8867#endif
8868 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008869 if (!in->realtime) {
8870 in->config = pcm_config_audio_capture;
8871 frame_size = audio_stream_in_frame_size(&in->stream);
8872 buffer_size = get_input_buffer_size(config->sample_rate,
8873 config->format,
8874 channel_count,
8875 is_low_latency);
8876 in->config.period_size = buffer_size / frame_size;
8877 in->config.rate = config->sample_rate;
8878 in->af_period_multiplier = 1;
8879 } else {
8880 // period size is left untouched for rt mode playback
8881 in->config = pcm_config_audio_capture_rt;
8882 in->af_period_multiplier = af_period_multiplier;
8883 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008884 }
8885
8886 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8887 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8888 in->realtime = 0;
8889 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8890 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008891 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008892 in->stream.start = in_start;
8893 in->stream.stop = in_stop;
8894 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8895 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008896 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8897 } else if (in->realtime) {
8898 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008899 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008900 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008901 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008902 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8903 in->config = pcm_config_audio_capture;
8904 frame_size = audio_stream_in_frame_size(&in->stream);
8905 buffer_size = get_input_buffer_size(config->sample_rate,
8906 config->format,
8907 channel_count,
8908 false /*is_low_latency*/);
8909 in->config.period_size = buffer_size / frame_size;
8910 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008911 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008912 switch (config->format) {
8913 case AUDIO_FORMAT_PCM_32_BIT:
8914 in->bit_width = 32;
8915 break;
8916 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8917 case AUDIO_FORMAT_PCM_8_24_BIT:
8918 in->bit_width = 24;
8919 break;
8920 default:
8921 in->bit_width = 16;
8922 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008923 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308924 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008925 if (config->sample_rate == 0)
8926 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8927 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8928 config->sample_rate != 8000) {
8929 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8930 ret = -EINVAL;
8931 goto err_open;
8932 }
8933 if (config->format == AUDIO_FORMAT_DEFAULT)
8934 config->format = AUDIO_FORMAT_PCM_16_BIT;
8935 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8936 config->format = AUDIO_FORMAT_PCM_16_BIT;
8937 ret = -EINVAL;
8938 goto err_open;
8939 }
8940
8941 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8942 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008943 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008944 in->af_period_multiplier = 1;
8945 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8946 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8947 (config->sample_rate == 8000 ||
8948 config->sample_rate == 16000 ||
8949 config->sample_rate == 32000 ||
8950 config->sample_rate == 48000) &&
8951 channel_count == 1) {
8952 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8953 in->config = pcm_config_audio_capture;
8954 frame_size = audio_stream_in_frame_size(&in->stream);
8955 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8956 config->sample_rate,
8957 config->format,
8958 channel_count, false /*is_low_latency*/);
8959 in->config.period_size = buffer_size / frame_size;
8960 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8961 in->config.rate = config->sample_rate;
8962 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008963 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308964 int ret_val;
8965 pthread_mutex_lock(&adev->lock);
8966 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8967 in, config, &channel_mask_updated);
8968 pthread_mutex_unlock(&adev->lock);
8969
8970 if (!ret_val) {
8971 if (channel_mask_updated == true) {
8972 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8973 __func__, config->channel_mask);
8974 ret = -EINVAL;
8975 goto err_open;
8976 }
8977 ALOGD("%s: created multi-channel session succesfully",__func__);
8978 } else if (audio_extn_compr_cap_enabled() &&
8979 audio_extn_compr_cap_format_supported(config->format) &&
8980 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8981 audio_extn_compr_cap_init(in);
8982 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05308983 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308984 if (ret)
8985 goto err_open;
8986 } else {
8987 in->config = pcm_config_audio_capture;
8988 in->config.rate = config->sample_rate;
8989 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308990 in->format = config->format;
8991 frame_size = audio_stream_in_frame_size(&in->stream);
8992 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008993 config->format,
8994 channel_count,
8995 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008996 /* prevent division-by-zero */
8997 if (frame_size == 0) {
8998 ALOGE("%s: Error frame_size==0", __func__);
8999 ret = -EINVAL;
9000 goto err_open;
9001 }
9002
Revathi Uddarajud2634032017-12-07 14:42:34 +05309003 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009004 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009005
Revathi Uddarajud2634032017-12-07 14:42:34 +05309006 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9007 /* optionally use VOIP usecase depending on config(s) */
9008 ret = adev_update_voice_comm_input_stream(in, config);
9009 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009010
Revathi Uddarajud2634032017-12-07 14:42:34 +05309011 if (ret) {
9012 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9013 goto err_open;
9014 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009015 }
Samyak Jainc37062f2019-04-25 18:41:06 +05309016 if (audio_extn_is_concurrent_capture_enabled()) {
9017 /* Acquire lock to avoid two concurrent use cases initialized to
9018 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009019
Samyak Jainc37062f2019-04-25 18:41:06 +05309020 if (in->usecase == USECASE_AUDIO_RECORD) {
9021 pthread_mutex_lock(&adev->lock);
9022 if (!(adev->pcm_record_uc_state)) {
9023 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9024 adev->pcm_record_uc_state = 1;
9025 pthread_mutex_unlock(&adev->lock);
9026 } else {
9027 pthread_mutex_unlock(&adev->lock);
9028 /* Assign compress record use case for second record */
9029 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9030 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9031 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9032 if (audio_extn_cin_applicable_stream(in)) {
9033 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309034 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309035 if (ret)
9036 goto err_open;
9037 }
9038 }
9039 }
kunleiz28c73e72019-03-27 17:24:04 +08009040 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009041 }
Ramjee Singh8b09cc12019-08-21 16:31:33 +05309042 if (audio_extn_ssr_get_stream() != in)
9043 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009044
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009045 in->sample_rate = in->config.rate;
9046
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309047 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9048 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009049 devices, flags, in->format,
9050 in->sample_rate, in->bit_width,
9051 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309052 register_format(in->format, in->supported_formats);
9053 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9054 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309055
Aalique Grahame22e49102018-12-18 14:23:57 -08009056 in->error_log = error_log_create(
9057 ERROR_LOG_ENTRIES,
9058 1000000000 /* aggregate consecutive identical errors within one second */);
9059
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009060 /* This stream could be for sound trigger lab,
9061 get sound trigger pcm if present */
9062 audio_extn_sound_trigger_check_and_get_session(in);
9063
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309064 lock_input_stream(in);
9065 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9066 pthread_mutex_lock(&adev->lock);
9067 in->card_status = adev->card_status;
9068 pthread_mutex_unlock(&adev->lock);
9069 pthread_mutex_unlock(&in->lock);
9070
Aalique Grahame22e49102018-12-18 14:23:57 -08009071 stream_app_type_cfg_init(&in->app_type_cfg);
9072
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009073 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009074
9075 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9076 calloc(1, sizeof(streams_input_ctxt_t));
9077 if (in_ctxt == NULL) {
9078 ALOGE("%s fail to allocate input ctxt", __func__);
9079 ret = -ENOMEM;
9080 goto err_open;
9081 }
9082 in_ctxt->input = in;
9083
9084 pthread_mutex_lock(&adev->lock);
9085 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9086 pthread_mutex_unlock(&adev->lock);
9087
Eric Laurent994a6932013-07-17 11:51:42 -07009088 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009089 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009090
9091err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309092 if (in->usecase == USECASE_AUDIO_RECORD) {
9093 pthread_mutex_lock(&adev->lock);
9094 adev->pcm_record_uc_state = 0;
9095 pthread_mutex_unlock(&adev->lock);
9096 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009097 free(in);
9098 *stream_in = NULL;
9099 return ret;
9100}
9101
9102static void adev_close_input_stream(struct audio_hw_device *dev,
9103 struct audio_stream_in *stream)
9104{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009105 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009106 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009107 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309108
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309109 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009110
kunleiz70e57612018-12-28 17:50:23 +08009111 /* must deregister from sndmonitor first to prevent races
9112 * between the callback and close_stream
9113 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309114 audio_extn_snd_mon_unregister_listener(stream);
9115
kunleiz70e57612018-12-28 17:50:23 +08009116 /* Disable echo reference if there are no active input, hfp call
9117 * and sound trigger while closing input stream
9118 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009119 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009120 !audio_extn_hfp_is_active(adev) &&
9121 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08009122 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08009123 else
9124 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309125
Pallavid7c7a272018-01-16 11:22:55 +05309126 if (in == NULL) {
9127 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9128 return;
9129 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08009130 error_log_destroy(in->error_log);
9131 in->error_log = NULL;
9132
Pallavid7c7a272018-01-16 11:22:55 +05309133
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009134 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309135 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009136 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309137 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009138 if (ret != 0)
9139 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9140 __func__, ret);
9141 } else
9142 in_standby(&stream->common);
9143
Revathi Uddarajud2634032017-12-07 14:42:34 +05309144 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309145 if (in->usecase == USECASE_AUDIO_RECORD) {
9146 adev->pcm_record_uc_state = 0;
9147 }
9148
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009149 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009150 audio_extn_ssr_deinit();
9151 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009152
Garmond Leunge2433c32017-09-28 21:51:22 -07009153 if (audio_extn_ffv_get_stream() == in) {
9154 audio_extn_ffv_stream_deinit();
9155 }
9156
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309157 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009158 audio_extn_compr_cap_format_supported(in->config.format))
9159 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309160
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309161 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05309162 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009163
Mingming Yinfd7607b2016-01-22 12:48:44 -08009164 if (in->is_st_session) {
9165 ALOGV("%s: sound trigger pcm stop lab", __func__);
9166 audio_extn_sound_trigger_stop_lab(in);
9167 }
Derek Chenf939fb72018-11-13 13:34:41 -08009168 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9169 if (in_ctxt != NULL) {
9170 list_remove(&in_ctxt->list);
9171 free(in_ctxt);
9172 } else {
9173 ALOGW("%s, input stream already closed", __func__);
9174 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009175 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309176 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009177 return;
9178}
9179
Aalique Grahame22e49102018-12-18 14:23:57 -08009180/* verifies input and output devices and their capabilities.
9181 *
9182 * This verification is required when enabling extended bit-depth or
9183 * sampling rates, as not all qcom products support it.
9184 *
9185 * Suitable for calling only on initialization such as adev_open().
9186 * It fills the audio_device use_case_table[] array.
9187 *
9188 * Has a side-effect that it needs to configure audio routing / devices
9189 * in order to power up the devices and read the device parameters.
9190 * It does not acquire any hw device lock. Should restore the devices
9191 * back to "normal state" upon completion.
9192 */
9193static int adev_verify_devices(struct audio_device *adev)
9194{
9195 /* enumeration is a bit difficult because one really wants to pull
9196 * the use_case, device id, etc from the hidden pcm_device_table[].
9197 * In this case there are the following use cases and device ids.
9198 *
9199 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9200 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9201 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9202 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9203 * [USECASE_AUDIO_RECORD] = {0, 0},
9204 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9205 * [USECASE_VOICE_CALL] = {2, 2},
9206 *
9207 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9208 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9209 */
9210
9211 /* should be the usecases enabled in adev_open_input_stream() */
9212 static const int test_in_usecases[] = {
9213 USECASE_AUDIO_RECORD,
9214 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9215 };
9216 /* should be the usecases enabled in adev_open_output_stream()*/
9217 static const int test_out_usecases[] = {
9218 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9219 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9220 };
9221 static const usecase_type_t usecase_type_by_dir[] = {
9222 PCM_PLAYBACK,
9223 PCM_CAPTURE,
9224 };
9225 static const unsigned flags_by_dir[] = {
9226 PCM_OUT,
9227 PCM_IN,
9228 };
9229
9230 size_t i;
9231 unsigned dir;
9232 const unsigned card_id = adev->snd_card;
9233
9234 for (dir = 0; dir < 2; ++dir) {
9235 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9236 const unsigned flags_dir = flags_by_dir[dir];
9237 const size_t testsize =
9238 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9239 const int *testcases =
9240 dir ? test_in_usecases : test_out_usecases;
9241 const audio_devices_t audio_device =
9242 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9243
9244 for (i = 0; i < testsize; ++i) {
9245 const audio_usecase_t audio_usecase = testcases[i];
9246 int device_id;
9247 struct pcm_params **pparams;
9248 struct stream_out out;
9249 struct stream_in in;
9250 struct audio_usecase uc_info;
9251 int retval;
9252
9253 pparams = &adev->use_case_table[audio_usecase];
9254 pcm_params_free(*pparams); /* can accept null input */
9255 *pparams = NULL;
9256
9257 /* find the device ID for the use case (signed, for error) */
9258 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9259 if (device_id < 0)
9260 continue;
9261
9262 /* prepare structures for device probing */
9263 memset(&uc_info, 0, sizeof(uc_info));
9264 uc_info.id = audio_usecase;
9265 uc_info.type = usecase_type;
9266 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009267 memset(&in, 0, sizeof(in));
9268 in.device = audio_device;
9269 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9270 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009271 }
9272 memset(&out, 0, sizeof(out));
9273 out.devices = audio_device; /* only field needed in select_devices */
9274 uc_info.stream.out = &out;
9275 uc_info.devices = audio_device;
9276 uc_info.in_snd_device = SND_DEVICE_NONE;
9277 uc_info.out_snd_device = SND_DEVICE_NONE;
9278 list_add_tail(&adev->usecase_list, &uc_info.list);
9279
9280 /* select device - similar to start_(in/out)put_stream() */
9281 retval = select_devices(adev, audio_usecase);
9282 if (retval >= 0) {
9283 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9284#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009285 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009286 if (*pparams) {
9287 ALOGV("%s: (%s) card %d device %d", __func__,
9288 dir ? "input" : "output", card_id, device_id);
9289 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9290 } else {
9291 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9292 }
9293#endif
9294 }
9295
9296 /* deselect device - similar to stop_(in/out)put_stream() */
9297 /* 1. Get and set stream specific mixer controls */
9298 retval = disable_audio_route(adev, &uc_info);
9299 /* 2. Disable the rx device */
9300 retval = disable_snd_device(adev,
9301 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9302 list_remove(&uc_info.list);
9303 }
9304 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009305 return 0;
9306}
9307
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309308int adev_create_audio_patch(struct audio_hw_device *dev,
9309 unsigned int num_sources,
9310 const struct audio_port_config *sources,
9311 unsigned int num_sinks,
9312 const struct audio_port_config *sinks,
9313 audio_patch_handle_t *handle)
9314{
Derek Chenf939fb72018-11-13 13:34:41 -08009315 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309316
Derek Chenf939fb72018-11-13 13:34:41 -08009317 ret = audio_extn_hw_loopback_create_audio_patch(dev,
9318 num_sources,
9319 sources,
9320 num_sinks,
9321 sinks,
9322 handle);
9323 ret |= audio_extn_auto_hal_create_audio_patch(dev,
9324 num_sources,
9325 sources,
9326 num_sinks,
9327 sinks,
9328 handle);
9329 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309330}
9331
9332int adev_release_audio_patch(struct audio_hw_device *dev,
9333 audio_patch_handle_t handle)
9334{
Derek Chenf939fb72018-11-13 13:34:41 -08009335 int ret;
9336
9337 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
9338 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
9339 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309340}
9341
9342int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9343{
Derek Chenf13dd492018-11-13 14:53:51 -08009344 int ret = 0;
9345
9346 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9347 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9348 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309349}
9350
9351int adev_set_audio_port_config(struct audio_hw_device *dev,
9352 const struct audio_port_config *config)
9353{
Derek Chenf13dd492018-11-13 14:53:51 -08009354 int ret = 0;
9355
9356 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9357 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9358 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309359}
9360
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009361static int adev_dump(const audio_hw_device_t *device __unused,
9362 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009363{
9364 return 0;
9365}
9366
9367static int adev_close(hw_device_t *device)
9368{
Aalique Grahame22e49102018-12-18 14:23:57 -08009369 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309370 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009371
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309372 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009373 return 0;
9374
9375 pthread_mutex_lock(&adev_init_lock);
9376
9377 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309378 if (audio_extn_spkr_prot_is_enabled())
9379 audio_extn_spkr_prot_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309380 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009381 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009382 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009383 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009384 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309385 audio_extn_utils_release_streams_cfg_lists(
9386 &adev->streams_output_cfg_list,
9387 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309388 if (audio_extn_qap_is_enabled())
9389 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309390 if (audio_extn_qaf_is_enabled())
9391 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009392 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009393 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009394 free(adev->snd_dev_ref_cnt);
9395 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009396 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9397 pcm_params_free(adev->use_case_table[i]);
9398 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009399 if (adev->adm_deinit)
9400 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309401 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009402 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309403 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309404 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009405 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309406 if (adev->device_cfg_params) {
9407 free(adev->device_cfg_params);
9408 adev->device_cfg_params = NULL;
9409 }
Derek Chend2530072014-11-24 12:39:14 -08009410 if(adev->ext_hw_plugin)
9411 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009412 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009413 free(device);
9414 adev = NULL;
9415 }
9416 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309417 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009418 return 0;
9419}
9420
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009421/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9422 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9423 * just that it _might_ work.
9424 */
9425static int period_size_is_plausible_for_low_latency(int period_size)
9426{
9427 switch (period_size) {
9428 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009429 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009430 case 240:
9431 case 320:
9432 case 480:
9433 return 1;
9434 default:
9435 return 0;
9436 }
9437}
9438
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309439static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9440{
9441 bool is_snd_card_status = false;
9442 bool is_ext_device_status = false;
9443 char value[32];
9444 int card = -1;
9445 card_status_t status;
9446
9447 if (cookie != adev || !parms)
9448 return;
9449
9450 if (!parse_snd_card_status(parms, &card, &status)) {
9451 is_snd_card_status = true;
9452 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9453 is_ext_device_status = true;
9454 } else {
9455 // not a valid event
9456 return;
9457 }
9458
9459 pthread_mutex_lock(&adev->lock);
9460 if (card == adev->snd_card || is_ext_device_status) {
9461 if (is_snd_card_status && adev->card_status != status) {
9462 adev->card_status = status;
9463 platform_snd_card_update(adev->platform, status);
9464 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -08009465 audio_extn_auto_hal_set_parameters(adev, parms);
Zhou Song5f7908f2019-07-02 00:32:23 +08009466 if (status == CARD_STATUS_OFFLINE)
9467 audio_extn_sco_reset_configuration();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309468 } else if (is_ext_device_status) {
9469 platform_set_parameters(adev->platform, parms);
9470 }
9471 }
9472 pthread_mutex_unlock(&adev->lock);
9473 return;
9474}
9475
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309476/* out and adev lock held */
9477static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9478{
9479 struct audio_usecase *uc_info;
9480 float left_p;
9481 float right_p;
9482 audio_devices_t devices;
9483
9484 uc_info = get_usecase_from_list(adev, out->usecase);
9485 if (uc_info == NULL) {
9486 ALOGE("%s: Could not find the usecase (%d) in the list",
9487 __func__, out->usecase);
9488 return -EINVAL;
9489 }
9490
9491 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9492 out->usecase, use_case_table[out->usecase]);
9493
9494 if (restore) {
9495 // restore A2DP device for active usecases and unmute if required
9496 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9497 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9498 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9499 select_devices(adev, uc_info->id);
9500 pthread_mutex_lock(&out->compr_mute_lock);
9501 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05309502 (out->a2dp_compress_mute) && (uc_info->out_snd_device == SND_DEVICE_OUT_BT_A2DP)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309503 out->a2dp_compress_mute = false;
9504 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9505 }
9506 pthread_mutex_unlock(&out->compr_mute_lock);
9507 }
9508 } else {
Zhou Song28023002019-09-09 14:17:40 +08009509 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
9510 // mute compress stream if suspended
9511 pthread_mutex_lock(&out->compr_mute_lock);
9512 if (!out->a2dp_compress_mute && !out->standby) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309513 ALOGD("%s: selecting speaker and muting stream", __func__);
9514 devices = out->devices;
9515 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9516 left_p = out->volume_l;
9517 right_p = out->volume_r;
9518 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9519 compress_pause(out->compr);
9520 out_set_compr_volume(&out->stream, (float)0, (float)0);
9521 out->a2dp_compress_mute = true;
9522 select_devices(adev, out->usecase);
9523 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9524 compress_resume(out->compr);
9525 out->devices = devices;
9526 out->volume_l = left_p;
9527 out->volume_r = right_p;
9528 }
Zhou Song28023002019-09-09 14:17:40 +08009529 pthread_mutex_unlock(&out->compr_mute_lock);
9530 } else {
9531 // tear down a2dp path for non offloaded streams
9532 if (audio_extn_a2dp_source_is_suspended())
9533 out_standby_l(&out->stream.common);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309534 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309535 }
9536 ALOGV("%s: exit", __func__);
9537 return 0;
9538}
9539
9540int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9541{
9542 int ret = 0;
9543
9544 lock_output_stream(out);
9545 pthread_mutex_lock(&adev->lock);
9546
9547 ret = check_a2dp_restore_l(adev, out, restore);
9548
9549 pthread_mutex_unlock(&adev->lock);
9550 pthread_mutex_unlock(&out->lock);
9551 return ret;
9552}
9553
Haynes Mathew George01156f92018-04-13 15:29:54 -07009554void adev_on_battery_status_changed(bool charging)
9555{
9556 pthread_mutex_lock(&adev->lock);
9557 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9558 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009559 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009560 pthread_mutex_unlock(&adev->lock);
9561}
9562
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009563static int adev_open(const hw_module_t *module, const char *name,
9564 hw_device_t **device)
9565{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309566 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009567 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309568 char mixer_ctl_name[128] = {0};
9569 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309570
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009571 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009572 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9573
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009574 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009575 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009576 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009577 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009578 ALOGD("%s: returning existing instance of adev", __func__);
9579 ALOGD("%s: exit", __func__);
9580 pthread_mutex_unlock(&adev_init_lock);
9581 return 0;
9582 }
9583
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009584 adev = calloc(1, sizeof(struct audio_device));
9585
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009586 if (!adev) {
9587 pthread_mutex_unlock(&adev_init_lock);
9588 return -ENOMEM;
9589 }
9590
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009591 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9592
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009593 // register audio ext hidl at the earliest
9594 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309595#ifdef DYNAMIC_LOG_ENABLED
9596 register_for_dynamic_logging("hal");
9597#endif
9598
Derek Chenf939fb72018-11-13 13:34:41 -08009599 /* default audio HAL major version */
9600 uint32_t maj_version = 2;
9601 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9602 maj_version = atoi(value);
9603
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009604 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009605 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009606 adev->device.common.module = (struct hw_module_t *)module;
9607 adev->device.common.close = adev_close;
9608
9609 adev->device.init_check = adev_init_check;
9610 adev->device.set_voice_volume = adev_set_voice_volume;
9611 adev->device.set_master_volume = adev_set_master_volume;
9612 adev->device.get_master_volume = adev_get_master_volume;
9613 adev->device.set_master_mute = adev_set_master_mute;
9614 adev->device.get_master_mute = adev_get_master_mute;
9615 adev->device.set_mode = adev_set_mode;
9616 adev->device.set_mic_mute = adev_set_mic_mute;
9617 adev->device.get_mic_mute = adev_get_mic_mute;
9618 adev->device.set_parameters = adev_set_parameters;
9619 adev->device.get_parameters = adev_get_parameters;
9620 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9621 adev->device.open_output_stream = adev_open_output_stream;
9622 adev->device.close_output_stream = adev_close_output_stream;
9623 adev->device.open_input_stream = adev_open_input_stream;
9624 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309625 adev->device.create_audio_patch = adev_create_audio_patch;
9626 adev->device.release_audio_patch = adev_release_audio_patch;
9627 adev->device.get_audio_port = adev_get_audio_port;
9628 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009629 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309630 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009631
9632 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009633 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009634 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009635 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009636 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009637 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009638 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309639 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009640 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009641 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009642 /* Init audio and voice feature */
9643 audio_extn_feature_init();
9644 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009645 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009646 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009647 list_init(&adev->active_inputs_list);
9648 list_init(&adev->active_outputs_list);
Rahul Sharma99770982019-03-06 17:05:26 +05309649 list_init(&adev->audio_patch_record_list);
9650 adev->audio_patch_index = 0;
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009651 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009652 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309653 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309654 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309655 adev->perf_lock_opts[0] = 0x101;
9656 adev->perf_lock_opts[1] = 0x20E;
9657 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009658 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009659 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309660 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009661 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009663 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009664 adev->platform = platform_init(adev);
9665 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009666 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009667 free(adev->snd_dev_ref_cnt);
9668 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009669 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009670 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9671 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009672 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009673 return -EINVAL;
9674 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009675
Aalique Grahame22e49102018-12-18 14:23:57 -08009676 adev->extspk = audio_extn_extspk_init(adev);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309677 if (audio_extn_qap_is_enabled()) {
9678 ret = audio_extn_qap_init(adev);
9679 if (ret < 0) {
9680 pthread_mutex_destroy(&adev->lock);
9681 free(adev);
9682 adev = NULL;
9683 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9684 *device = NULL;
9685 pthread_mutex_unlock(&adev_init_lock);
9686 return ret;
9687 }
9688 adev->device.open_output_stream = audio_extn_qap_open_output_stream;
9689 adev->device.close_output_stream = audio_extn_qap_close_output_stream;
9690 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009691
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309692 if (audio_extn_qaf_is_enabled()) {
9693 ret = audio_extn_qaf_init(adev);
9694 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009695 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309696 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009697 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309698 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9699 *device = NULL;
9700 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309701 return ret;
9702 }
9703
9704 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9705 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9706 }
9707
Derek Chenae7b0342019-02-08 15:17:04 -08009708 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009709 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9710
Eric Laurentc4aef752013-09-12 17:45:53 -07009711 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9712 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9713 if (adev->visualizer_lib == NULL) {
9714 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9715 } else {
9716 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9717 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009718 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009719 "visualizer_hal_start_output");
9720 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009721 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009722 "visualizer_hal_stop_output");
9723 }
9724 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309725 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009726 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009727 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009728 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309729 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009730 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009731
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009732 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9733 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9734 if (adev->offload_effects_lib == NULL) {
9735 ALOGE("%s: DLOPEN failed for %s", __func__,
9736 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9737 } else {
9738 ALOGV("%s: DLOPEN successful for %s", __func__,
9739 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9740 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309741 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009742 "offload_effects_bundle_hal_start_output");
9743 adev->offload_effects_stop_output =
9744 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9745 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009746 adev->offload_effects_set_hpx_state =
9747 (int (*)(bool))dlsym(adev->offload_effects_lib,
9748 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309749 adev->offload_effects_get_parameters =
9750 (void (*)(struct str_parms *, struct str_parms *))
9751 dlsym(adev->offload_effects_lib,
9752 "offload_effects_bundle_get_parameters");
9753 adev->offload_effects_set_parameters =
9754 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9755 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009756 }
9757 }
9758
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009759 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9760 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9761 if (adev->adm_lib == NULL) {
9762 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9763 } else {
9764 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9765 adev->adm_init = (adm_init_t)
9766 dlsym(adev->adm_lib, "adm_init");
9767 adev->adm_deinit = (adm_deinit_t)
9768 dlsym(adev->adm_lib, "adm_deinit");
9769 adev->adm_register_input_stream = (adm_register_input_stream_t)
9770 dlsym(adev->adm_lib, "adm_register_input_stream");
9771 adev->adm_register_output_stream = (adm_register_output_stream_t)
9772 dlsym(adev->adm_lib, "adm_register_output_stream");
9773 adev->adm_deregister_stream = (adm_deregister_stream_t)
9774 dlsym(adev->adm_lib, "adm_deregister_stream");
9775 adev->adm_request_focus = (adm_request_focus_t)
9776 dlsym(adev->adm_lib, "adm_request_focus");
9777 adev->adm_abandon_focus = (adm_abandon_focus_t)
9778 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009779 adev->adm_set_config = (adm_set_config_t)
9780 dlsym(adev->adm_lib, "adm_set_config");
9781 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9782 dlsym(adev->adm_lib, "adm_request_focus_v2");
9783 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9784 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9785 adev->adm_on_routing_change = (adm_on_routing_change_t)
9786 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009787 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9788 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009789 }
9790 }
9791
Aalique Grahame22e49102018-12-18 14:23:57 -08009792 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009793 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009794 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009795 //initialize this to false for now,
9796 //this will be set to true through set param
9797 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009798
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009799 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009800 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009801
9802 if (k_enable_extended_precision)
9803 adev_verify_devices(adev);
9804
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009805 adev->dsp_bit_width_enforce_mode =
9806 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009807
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309808 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9809 &adev->streams_output_cfg_list,
9810 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009811
Kiran Kandi910e1862013-10-29 13:29:42 -07009812 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009813
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009814 int trial;
Manisha Agarwalbce6f6a2019-12-06 18:48:25 +05309815 if (property_get("vendor.audio_hal.period_size", value, NULL) > 0) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009816 trial = atoi(value);
9817 if (period_size_is_plausible_for_low_latency(trial)) {
9818 pcm_config_low_latency.period_size = trial;
9819 pcm_config_low_latency.start_threshold = trial / 4;
9820 pcm_config_low_latency.avail_min = trial / 4;
9821 configured_low_latency_capture_period_size = trial;
9822 }
9823 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009824 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9825 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009826 trial = atoi(value);
9827 if (period_size_is_plausible_for_low_latency(trial)) {
9828 configured_low_latency_capture_period_size = trial;
9829 }
9830 }
9831
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009832 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9833
Eric Laurent4b084132018-10-19 17:33:43 -07009834 adev->camera_orientation = CAMERA_DEFAULT;
9835
Manisha Agarwalbce6f6a2019-12-06 18:48:25 +05309836 if (property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009837 af_period_multiplier = atoi(value);
9838 if (af_period_multiplier < 0)
9839 af_period_multiplier = 2;
9840 else if (af_period_multiplier > 4)
9841 af_period_multiplier = 4;
9842
9843 ALOGV("new period_multiplier = %d", af_period_multiplier);
9844 }
9845
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009846 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009847
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009848 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009849 pthread_mutex_unlock(&adev_init_lock);
9850
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009851 if (adev->adm_init)
9852 adev->adm_data = adev->adm_init();
9853
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309854 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309855 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009856 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309857
9858 audio_extn_snd_mon_init();
9859 pthread_mutex_lock(&adev->lock);
9860 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9861 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009862 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9863 /*
9864 * if the battery state callback happens before charging can be queried,
9865 * it will be guarded with the adev->lock held in the cb function and so
9866 * the callback value will reflect the latest state
9867 */
9868 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309869 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009870 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009871 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009872 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309873 /* Allocate memory for Device config params */
9874 adev->device_cfg_params = (struct audio_device_config_param*)
9875 calloc(platform_get_max_codec_backend(),
9876 sizeof(struct audio_device_config_param));
9877 if (adev->device_cfg_params == NULL)
9878 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309879
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309880 /*
9881 * Check if new PSPD matrix mixer control is supported. If not
9882 * supported, then set flag so that old mixer ctrl is sent while
9883 * sending pspd coefficients on older kernel version. Query mixer
9884 * control for default pcm id and channel value one.
9885 */
9886 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9887 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9888
9889 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9890 if (!ctl) {
9891 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9892 __func__, mixer_ctl_name);
9893 adev->use_old_pspd_mix_ctrl = true;
9894 }
9895
Eric Laurent994a6932013-07-17 11:51:42 -07009896 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009897 return 0;
9898}
9899
9900static struct hw_module_methods_t hal_module_methods = {
9901 .open = adev_open,
9902};
9903
9904struct audio_module HAL_MODULE_INFO_SYM = {
9905 .common = {
9906 .tag = HARDWARE_MODULE_TAG,
9907 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9908 .hal_api_version = HARDWARE_HAL_API_VERSION,
9909 .id = AUDIO_HARDWARE_MODULE_ID,
9910 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009911 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009912 .methods = &hal_module_methods,
9913 },
9914};