blob: 5bbd595605b459e399838937ff52f6980797fbb4 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080072#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070096#define INVALID_OUT_VOLUME -1
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097
Aalique Grahame22e49102018-12-18 14:23:57 -080098#define RECORD_GAIN_MIN 0.0f
99#define RECORD_GAIN_MAX 1.0f
100#define RECORD_VOLUME_CTL_MAX 0x2000
101
102/* treat as unsigned Q1.13 */
103#define APP_TYPE_GAIN_DEFAULT 0x2000
104
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700105#define PROXY_OPEN_RETRY_COUNT 100
106#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800107
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800108#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
109 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
110 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
111#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
112 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800113
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700114#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700115#define DEFAULT_VOIP_BUF_DURATION_MS 20
116#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
117#define DEFAULT_VOIP_SAMP_RATE 48000
118
119#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
120
121struct pcm_config default_pcm_config_voip_copp = {
122 .channels = 1,
123 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
124 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
125 .period_count = 2,
126 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800127 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
128 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700129};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700130
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700131#define MIN_CHANNEL_COUNT 1
132#define DEFAULT_CHANNEL_COUNT 2
133#define MAX_HIFI_CHANNEL_COUNT 8
134
Aalique Grahame22e49102018-12-18 14:23:57 -0800135#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
136#define MAX_CHANNEL_COUNT 1
137#else
138#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
139#define XSTR(x) STR(x)
140#define STR(x) #x
141#endif
142
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700143static unsigned int configured_low_latency_capture_period_size =
144 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
145
Haynes Mathew George16081042017-05-31 17:16:49 -0700146#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
147#define MMAP_PERIOD_COUNT_MIN 32
148#define MMAP_PERIOD_COUNT_MAX 512
149#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
150
Aalique Grahame22e49102018-12-18 14:23:57 -0800151/* This constant enables extended precision handling.
152 * TODO The flag is off until more testing is done.
153 */
154static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700155extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800156
Eric Laurentb23d5282013-05-14 15:27:20 -0700157struct pcm_config pcm_config_deep_buffer = {
158 .channels = 2,
159 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
160 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
161 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
162 .format = PCM_FORMAT_S16_LE,
163 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
164 .stop_threshold = INT_MAX,
165 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166};
167
168struct pcm_config pcm_config_low_latency = {
169 .channels = 2,
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
171 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
172 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
173 .format = PCM_FORMAT_S16_LE,
174 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
175 .stop_threshold = INT_MAX,
176 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177};
178
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800179struct pcm_config pcm_config_haptics_audio = {
180 .channels = 1,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
183 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
186 .stop_threshold = INT_MAX,
187 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188};
189
190struct pcm_config pcm_config_haptics = {
191 .channels = 1,
192 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
193 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
194 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
195 .format = PCM_FORMAT_S16_LE,
196 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
197 .stop_threshold = INT_MAX,
198 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
199};
200
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700201static int af_period_multiplier = 4;
202struct pcm_config pcm_config_rt = {
203 .channels = 2,
204 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
205 .period_size = ULL_PERIOD_SIZE, //1 ms
206 .period_count = 512, //=> buffer size is 512ms
207 .format = PCM_FORMAT_S16_LE,
208 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
209 .stop_threshold = INT_MAX,
210 .silence_threshold = 0,
211 .silence_size = 0,
212 .avail_min = ULL_PERIOD_SIZE, //1 ms
213};
214
Eric Laurentb23d5282013-05-14 15:27:20 -0700215struct pcm_config pcm_config_hdmi_multi = {
216 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
217 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
218 .period_size = HDMI_MULTI_PERIOD_SIZE,
219 .period_count = HDMI_MULTI_PERIOD_COUNT,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = 0,
222 .stop_threshold = INT_MAX,
223 .avail_min = 0,
224};
225
Haynes Mathew George16081042017-05-31 17:16:49 -0700226struct pcm_config pcm_config_mmap_playback = {
227 .channels = 2,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = MMAP_PERIOD_SIZE*8,
233 .stop_threshold = INT32_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700239struct pcm_config pcm_config_hifi = {
240 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
241 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
242 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
243 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
244 .format = PCM_FORMAT_S24_3LE,
245 .start_threshold = 0,
246 .stop_threshold = INT_MAX,
247 .avail_min = 0,
248};
249
Eric Laurentb23d5282013-05-14 15:27:20 -0700250struct pcm_config pcm_config_audio_capture = {
251 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700252 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
253 .format = PCM_FORMAT_S16_LE,
254};
255
Haynes Mathew George16081042017-05-31 17:16:49 -0700256struct pcm_config pcm_config_mmap_capture = {
257 .channels = 2,
258 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
259 .period_size = MMAP_PERIOD_SIZE,
260 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
261 .format = PCM_FORMAT_S16_LE,
262 .start_threshold = 0,
263 .stop_threshold = INT_MAX,
264 .silence_threshold = 0,
265 .silence_size = 0,
266 .avail_min = MMAP_PERIOD_SIZE, //1 ms
267};
268
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700269#define AFE_PROXY_CHANNEL_COUNT 2
270#define AFE_PROXY_SAMPLING_RATE 48000
271
272#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
273#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
274
275struct pcm_config pcm_config_afe_proxy_playback = {
276 .channels = AFE_PROXY_CHANNEL_COUNT,
277 .rate = AFE_PROXY_SAMPLING_RATE,
278 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
279 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
280 .format = PCM_FORMAT_S16_LE,
281 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
282 .stop_threshold = INT_MAX,
283 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284};
285
286#define AFE_PROXY_RECORD_PERIOD_SIZE 768
287#define AFE_PROXY_RECORD_PERIOD_COUNT 4
288
Aalique Grahame22e49102018-12-18 14:23:57 -0800289struct pcm_config pcm_config_audio_capture_rt = {
290 .channels = 2,
291 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
292 .period_size = ULL_PERIOD_SIZE,
293 .period_count = 512,
294 .format = PCM_FORMAT_S16_LE,
295 .start_threshold = 0,
296 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
297 .silence_threshold = 0,
298 .silence_size = 0,
299 .avail_min = ULL_PERIOD_SIZE, //1 ms
300};
301
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700302struct pcm_config pcm_config_afe_proxy_record = {
303 .channels = AFE_PROXY_CHANNEL_COUNT,
304 .rate = AFE_PROXY_SAMPLING_RATE,
305 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
306 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
307 .format = PCM_FORMAT_S16_LE,
308 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
309 .stop_threshold = INT_MAX,
310 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
311};
312
Ashish Jainf1eaa582016-05-23 20:54:24 +0530313#define AUDIO_MAX_PCM_FORMATS 7
314
315const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
316 [AUDIO_FORMAT_DEFAULT] = 0,
317 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
318 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
319 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
320 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
321 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
322 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
323};
324
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800325const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700326 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
327 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800328 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700329 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
330 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700331 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700332 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700333 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
334 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700341 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
342 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700343 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800344 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700345
Eric Laurentb23d5282013-05-14 15:27:20 -0700346 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700347 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530348 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
349 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
350 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530351 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
352 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700353 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700354 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700355 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700356 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700357
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800358 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800359 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700360 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700361
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700362 [USECASE_VOICE2_CALL] = "voice2-call",
363 [USECASE_VOLTE_CALL] = "volte-call",
364 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800365 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800366 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
367 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800368 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700369 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
370 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
371 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800372 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
373 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
374 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
375
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700376 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
377 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700378 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
379 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700380
381 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
382 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530383 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700384
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530385 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530386 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
387 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700388
389 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
390 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530391 /* For Interactive Audio Streams */
392 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700400
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800401 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
402
Derek Chenf6318be2017-06-12 17:16:24 -0400403 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
404
405 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
406 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
407 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
408 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Rahul Sharma99770982019-03-06 17:05:26 +0530409 [USECASE_AUDIO_FM_TUNER_EXT] = "fm-tuner-ext",
Eric Laurentb23d5282013-05-14 15:27:20 -0700410};
411
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700412static const audio_usecase_t offload_usecases[] = {
413 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700414 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
415 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
416 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
417 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
418 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
419 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
421 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700422};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800423
Varun Balaraje49253e2017-07-06 19:48:56 +0530424static const audio_usecase_t interactive_usecases[] = {
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
426 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
427 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
428 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
429 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
432 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
433};
434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800435#define STRING_TO_ENUM(string) { #string, string }
436
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437struct string_to_enum {
438 const char *name;
439 uint32_t value;
440};
441
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700442static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800444 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
445 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
446 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700447 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800450 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700451 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
452 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
453 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
455 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
456 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
457 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
458 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
461 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800462};
463
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700464static const struct string_to_enum formats_name_to_enum_table[] = {
465 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
466 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
467 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700468 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
469 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
470 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700471 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800472 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
473 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700474 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800475};
476
477//list of all supported sample rates by HDMI specification.
478static const int out_hdmi_sample_rates[] = {
479 32000, 44100, 48000, 88200, 96000, 176400, 192000,
480};
481
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700482static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800483 STRING_TO_ENUM(32000),
484 STRING_TO_ENUM(44100),
485 STRING_TO_ENUM(48000),
486 STRING_TO_ENUM(88200),
487 STRING_TO_ENUM(96000),
488 STRING_TO_ENUM(176400),
489 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700490};
491
Carter Hsu2e429db2019-05-14 18:50:52 +0800492struct in_effect_list {
493 struct listnode list;
494 effect_handle_t handle;
495};
496
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700497static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700498static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700499static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700500//cache last MBDRC cal step level
501static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700502
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530503static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
504static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700505static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800506static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530507static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530508
Derek Chen6f293672019-04-01 01:40:24 -0700509static void adev_snd_mon_cb(void *cookie, struct str_parms *parms);
510static void in_snd_mon_cb(void * stream, struct str_parms * parms);
511static void out_snd_mon_cb(void * stream, struct str_parms * parms);
512
Zhou Song4721e282019-08-26 14:16:12 +0800513static int configure_btsco_sample_rate(snd_device_t snd_device);
514
Vatsal Buchac09ae062018-11-14 13:25:08 +0530515#ifdef AUDIO_FEATURE_ENABLED_GCOV
516extern void __gcov_flush();
517static void enable_gcov()
518{
519 __gcov_flush();
520}
521#else
522static void enable_gcov()
523{
524}
525#endif
526
justinweng20fb6d82019-02-21 18:49:00 -0700527static int in_set_microphone_direction(const struct audio_stream_in *stream,
528 audio_microphone_direction_t dir);
529static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
530
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700531static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
532 int flags __unused)
533{
534 int dir = 0;
535 switch (uc_id) {
536 case USECASE_AUDIO_RECORD_LOW_LATENCY:
537 dir = 1;
538 case USECASE_AUDIO_PLAYBACK_ULL:
539 break;
540 default:
541 return false;
542 }
543
544 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
545 PCM_PLAYBACK : PCM_CAPTURE);
546 if (adev->adm_is_noirq_avail)
547 return adev->adm_is_noirq_avail(adev->adm_data,
548 adev->snd_card, dev_id, dir);
549 return false;
550}
551
552static void register_out_stream(struct stream_out *out)
553{
554 struct audio_device *adev = out->dev;
555 if (is_offload_usecase(out->usecase) ||
556 !adev->adm_register_output_stream)
557 return;
558
559 // register stream first for backward compatibility
560 adev->adm_register_output_stream(adev->adm_data,
561 out->handle,
562 out->flags);
563
564 if (!adev->adm_set_config)
565 return;
566
567 if (out->realtime)
568 adev->adm_set_config(adev->adm_data,
569 out->handle,
570 out->pcm, &out->config);
571}
572
573static void register_in_stream(struct stream_in *in)
574{
575 struct audio_device *adev = in->dev;
576 if (!adev->adm_register_input_stream)
577 return;
578
579 adev->adm_register_input_stream(adev->adm_data,
580 in->capture_handle,
581 in->flags);
582
583 if (!adev->adm_set_config)
584 return;
585
586 if (in->realtime)
587 adev->adm_set_config(adev->adm_data,
588 in->capture_handle,
589 in->pcm,
590 &in->config);
591}
592
593static void request_out_focus(struct stream_out *out, long ns)
594{
595 struct audio_device *adev = out->dev;
596
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700597 if (adev->adm_request_focus_v2)
598 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
599 else if (adev->adm_request_focus)
600 adev->adm_request_focus(adev->adm_data, out->handle);
601}
602
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700603static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700604{
605 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700606 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700607
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700608 if (adev->adm_request_focus_v2_1)
609 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
610 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700611 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
612 else if (adev->adm_request_focus)
613 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700614
615 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700616}
617
618static void release_out_focus(struct stream_out *out)
619{
620 struct audio_device *adev = out->dev;
621
622 if (adev->adm_abandon_focus)
623 adev->adm_abandon_focus(adev->adm_data, out->handle);
624}
625
626static void release_in_focus(struct stream_in *in)
627{
628 struct audio_device *adev = in->dev;
629 if (adev->adm_abandon_focus)
630 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
631}
632
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530633static int parse_snd_card_status(struct str_parms *parms, int *card,
634 card_status_t *status)
635{
636 char value[32]={0};
637 char state[32]={0};
638
639 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
640 if (ret < 0)
641 return -1;
642
643 // sscanf should be okay as value is of max length 32.
644 // same as sizeof state.
645 if (sscanf(value, "%d,%s", card, state) < 2)
646 return -1;
647
648 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
649 CARD_STATUS_OFFLINE;
650 return 0;
651}
652
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700653static inline void adjust_frames_for_device_delay(struct stream_out *out,
654 uint32_t *dsp_frames) {
655 // Adjustment accounts for A2dp encoder latency with offload usecases
656 // Note: Encoder latency is returned in ms.
657 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
658 unsigned long offset =
659 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
660 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
661 }
662}
663
vivek mehtaa76401a2015-04-24 14:12:15 -0700664__attribute__ ((visibility ("default")))
665bool audio_hw_send_gain_dep_calibration(int level) {
666 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700667 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700668
669 pthread_mutex_lock(&adev_init_lock);
670
671 if (adev != NULL && adev->platform != NULL) {
672 pthread_mutex_lock(&adev->lock);
673 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700674
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530675 // cache level info for any of the use case which
676 // was not started.
677 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700678
vivek mehtaa76401a2015-04-24 14:12:15 -0700679 pthread_mutex_unlock(&adev->lock);
680 } else {
681 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
682 }
683
684 pthread_mutex_unlock(&adev_init_lock);
685
686 return ret_val;
687}
688
Ashish Jain5106d362016-05-11 19:23:33 +0530689static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
690{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800691 bool gapless_enabled = false;
692 const char *mixer_ctl_name = "Compress Gapless Playback";
693 struct mixer_ctl *ctl;
694
695 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700696 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530697
698 /*Disable gapless if its AV playback*/
699 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800700
701 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
702 if (!ctl) {
703 ALOGE("%s: Could not get ctl for mixer cmd - %s",
704 __func__, mixer_ctl_name);
705 return -EINVAL;
706 }
707
708 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
709 ALOGE("%s: Could not set gapless mode %d",
710 __func__, gapless_enabled);
711 return -EINVAL;
712 }
713 return 0;
714}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700715
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700716__attribute__ ((visibility ("default")))
717int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
718 int table_size) {
719 int ret_val = 0;
720 ALOGV("%s: enter ... ", __func__);
721
722 pthread_mutex_lock(&adev_init_lock);
723 if (adev == NULL) {
724 ALOGW("%s: adev is NULL .... ", __func__);
725 goto done;
726 }
727
728 pthread_mutex_lock(&adev->lock);
729 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
730 pthread_mutex_unlock(&adev->lock);
731done:
732 pthread_mutex_unlock(&adev_init_lock);
733 ALOGV("%s: exit ... ", __func__);
734 return ret_val;
735}
736
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800737bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800738{
739 bool ret = false;
740 ALOGV("%s: enter ...", __func__);
741
742 pthread_mutex_lock(&adev_init_lock);
743
744 if (adev != NULL && adev->platform != NULL) {
745 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800746 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800747 pthread_mutex_unlock(&adev->lock);
748 }
749
750 pthread_mutex_unlock(&adev_init_lock);
751
752 ALOGV("%s: exit with ret %d", __func__, ret);
753 return ret;
754}
Aalique Grahame22e49102018-12-18 14:23:57 -0800755
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700756static bool is_supported_format(audio_format_t format)
757{
Eric Laurent86e17132013-09-12 17:49:30 -0700758 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530759 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530760 format == AUDIO_FORMAT_AAC_LC ||
761 format == AUDIO_FORMAT_AAC_HE_V1 ||
762 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530763 format == AUDIO_FORMAT_AAC_ADTS_LC ||
764 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
765 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530766 format == AUDIO_FORMAT_AAC_LATM_LC ||
767 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
768 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530769 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
770 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530771 format == AUDIO_FORMAT_PCM_FLOAT ||
772 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700773 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530774 format == AUDIO_FORMAT_AC3 ||
775 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700776 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530777 format == AUDIO_FORMAT_DTS ||
778 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800779 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530780 format == AUDIO_FORMAT_ALAC ||
781 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530782 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530783 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800784 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530785 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700786 format == AUDIO_FORMAT_APTX ||
787 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800788 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700789
790 return false;
791}
792
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700793static inline bool is_mmap_usecase(audio_usecase_t uc_id)
794{
795 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
796 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
797}
798
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700799static inline bool is_valid_volume(float left, float right)
800{
801 return ((left >= 0.0f && right >= 0.0f) ? true : false);
802}
803
Avinash Vaish71a8b972014-07-24 15:36:33 +0530804static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
805 struct audio_usecase *uc_info)
806{
807 struct listnode *node;
808 struct audio_usecase *usecase;
809
810 if (uc_info == NULL)
811 return -EINVAL;
812
813 /* Re-route all voice usecases on the shared backend other than the
814 specified usecase to new snd devices */
815 list_for_each(node, &adev->usecase_list) {
816 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800817 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530818 enable_audio_route(adev, usecase);
819 }
820 return 0;
821}
822
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530823static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530824{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530825 ALOGV("%s", __func__);
826 audio_route_apply_and_update_path(adev->audio_route,
827 "asrc-mode");
828 adev->asrc_mode_enabled = true;
829}
830
831static void disable_asrc_mode(struct audio_device *adev)
832{
833 ALOGV("%s", __func__);
834 audio_route_reset_and_update_path(adev->audio_route,
835 "asrc-mode");
836 adev->asrc_mode_enabled = false;
837}
838
839/*
840 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
841 * 44.1 or Native DSD backends are enabled for any of current use case.
842 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
843 * - Disable current mix path use case(Headphone backend) and re-enable it with
844 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
845 * e.g. Naitve DSD or Headphone 44.1 -> + 48
846 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530847static void check_and_set_asrc_mode(struct audio_device *adev,
848 struct audio_usecase *uc_info,
849 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530850{
851 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530852 int i, num_new_devices = 0;
853 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
854 /*
855 *Split snd device for new combo use case
856 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
857 */
858 if (platform_split_snd_device(adev->platform,
859 snd_device,
860 &num_new_devices,
861 split_new_snd_devices) == 0) {
862 for (i = 0; i < num_new_devices; i++)
863 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
864 } else {
865 int new_backend_idx = platform_get_backend_index(snd_device);
866 if (((new_backend_idx == HEADPHONE_BACKEND) ||
867 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
868 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
869 !adev->asrc_mode_enabled) {
870 struct listnode *node = NULL;
871 struct audio_usecase *uc = NULL;
872 struct stream_out *curr_out = NULL;
873 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
874 int i, num_devices, ret = 0;
875 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530876
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530877 list_for_each(node, &adev->usecase_list) {
878 uc = node_to_item(node, struct audio_usecase, list);
879 curr_out = (struct stream_out*) uc->stream.out;
880 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
881 /*
882 *Split snd device for existing combo use case
883 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
884 */
885 ret = platform_split_snd_device(adev->platform,
886 uc->out_snd_device,
887 &num_devices,
888 split_snd_devices);
889 if (ret < 0 || num_devices == 0) {
890 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
891 split_snd_devices[0] = uc->out_snd_device;
892 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800893 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530894 for (i = 0; i < num_devices; i++) {
895 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
896 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
897 if((new_backend_idx == HEADPHONE_BACKEND) &&
898 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
899 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
900 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
901 __func__);
902 enable_asrc_mode(adev);
903 break;
904 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
905 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
906 (usecase_backend_idx == HEADPHONE_BACKEND)) {
907 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
908 __func__);
909 disable_audio_route(adev, uc);
910 disable_snd_device(adev, uc->out_snd_device);
911 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
912 if (new_backend_idx == DSD_NATIVE_BACKEND)
913 audio_route_apply_and_update_path(adev->audio_route,
914 "hph-true-highquality-mode");
915 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
916 (curr_out->bit_width >= 24))
917 audio_route_apply_and_update_path(adev->audio_route,
918 "hph-highquality-mode");
919 enable_asrc_mode(adev);
920 enable_snd_device(adev, uc->out_snd_device);
921 enable_audio_route(adev, uc);
922 break;
923 }
924 }
925 // reset split devices count
926 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800927 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530928 if (adev->asrc_mode_enabled)
929 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530930 }
931 }
932 }
933}
934
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700935static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
936 struct audio_effect_config effect_config,
937 unsigned int param_value)
938{
939 char mixer_ctl_name[] = "Audio Effect";
940 struct mixer_ctl *ctl;
941 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800942 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700943
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700944 if (in == NULL) {
945 ALOGE("%s: active input stream is NULL", __func__);
946 return -EINVAL;
947 }
948
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700949 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
950 if (!ctl) {
951 ALOGE("%s: Could not get mixer ctl - %s",
952 __func__, mixer_ctl_name);
953 return -EINVAL;
954 }
955
956 set_values[0] = 1; //0:Rx 1:Tx
957 set_values[1] = in->app_type_cfg.app_type;
958 set_values[2] = (long)effect_config.module_id;
959 set_values[3] = (long)effect_config.instance_id;
960 set_values[4] = (long)effect_config.param_id;
961 set_values[5] = param_value;
962
963 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
964
965 return 0;
966
967}
968
969static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
970 int effect_type, unsigned int *param_value)
971{
972 int ret = 0;
973 struct audio_effect_config other_effect_config;
974 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800975 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700976
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700977 if (in == NULL) {
978 ALOGE("%s: active input stream is NULL", __func__);
979 return -EINVAL;
980 }
981
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700982 usecase = get_usecase_from_list(adev, in->usecase);
983 if (!usecase)
984 return -EINVAL;
985
986 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
987 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
988 if (ret < 0) {
989 ALOGE("%s Failed to get effect params %d", __func__, ret);
990 return ret;
991 }
992
993 if (module_id == other_effect_config.module_id) {
994 //Same module id for AEC/NS. Values need to be combined
995 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
996 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
997 *param_value |= other_effect_config.param_value;
998 }
999 }
1000
1001 return ret;
1002}
1003
1004static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +05301005{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001006 struct audio_effect_config effect_config;
1007 struct audio_usecase *usecase = NULL;
1008 int ret = 0;
1009 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001010 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001011
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001012 if(!voice_extn_is_dynamic_ecns_enabled())
1013 return ENOSYS;
1014
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001015 if (!in) {
1016 ALOGE("%s: Invalid input stream", __func__);
1017 return -EINVAL;
1018 }
1019
1020 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1021
1022 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001023 if (usecase == NULL) {
1024 ALOGE("%s: Could not find the usecase (%d) in the list",
1025 __func__, in->usecase);
1026 return -EINVAL;
1027 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001028
1029 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1030 if (ret < 0) {
1031 ALOGE("%s Failed to get module id %d", __func__, ret);
1032 return ret;
1033 }
1034 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1035 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1036
1037 if(enable)
1038 param_value = effect_config.param_value;
1039
1040 /*Special handling for AEC & NS effects Param values need to be
1041 updated if module ids are same*/
1042
1043 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1044 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1045 if (ret < 0)
1046 return ret;
1047 }
1048
1049 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1050
1051 return ret;
1052}
1053
1054static void check_and_enable_effect(struct audio_device *adev)
1055{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001056 if(!voice_extn_is_dynamic_ecns_enabled())
1057 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001058
Eric Laurent637e2d42018-11-15 12:24:31 -08001059 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001060
Eric Laurent637e2d42018-11-15 12:24:31 -08001061 if (in != NULL && !in->standby) {
1062 if (in->enable_aec)
1063 enable_disable_effect(adev, EFFECT_AEC, true);
1064
1065 if (in->enable_ns &&
1066 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1067 enable_disable_effect(adev, EFFECT_NS, true);
1068 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001069 }
1070}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001071
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001072int pcm_ioctl(struct pcm *pcm, int request, ...)
1073{
1074 va_list ap;
1075 void * arg;
1076 int pcm_fd = *(int*)pcm;
1077
1078 va_start(ap, request);
1079 arg = va_arg(ap, void *);
1080 va_end(ap);
1081
1082 return ioctl(pcm_fd, request, arg);
1083}
1084
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001085int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001086 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001087{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001089 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301090 struct stream_out *out = NULL;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301091 struct stream_in *in = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301092 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001093
1094 if (usecase == NULL)
1095 return -EINVAL;
1096
1097 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1098
Carter Hsu2e429db2019-05-14 18:50:52 +08001099 if (usecase->type == PCM_CAPTURE) {
1100 struct stream_in *in = usecase->stream.in;
1101 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001102 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001103
1104 if (in) {
1105 if (in->enable_aec || in->enable_ec_port) {
1106 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
1107 struct listnode *node;
1108 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1109 USECASE_AUDIO_PLAYBACK_VOIP);
1110 if (voip_usecase) {
1111 out_device = voip_usecase->stream.out->devices;
1112 } else if (adev->primary_output &&
1113 !adev->primary_output->standby) {
1114 out_device = adev->primary_output->devices;
1115 } else {
1116 list_for_each(node, &adev->usecase_list) {
1117 uinfo = node_to_item(node, struct audio_usecase, list);
1118 if (uinfo->type != PCM_CAPTURE) {
1119 out_device = uinfo->stream.out->devices;
1120 break;
1121 }
1122 }
1123 }
1124 platform_set_echo_reference(adev, true, out_device);
1125 in->ec_opened = true;
1126 }
1127 }
1128 } else if (usecase->type == TRANSCODE_LOOPBACK_TX) {
1129 snd_device = usecase->in_snd_device;
1130 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001132 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001133
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001134#ifdef DS1_DOLBY_DAP_ENABLED
1135 audio_extn_dolby_set_dmid(adev);
1136 audio_extn_dolby_set_endpoint(adev);
1137#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001138 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001139 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301140 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001141 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001142 if (audio_extn_is_maxx_audio_enabled())
1143 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301144 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301145 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1146 out = usecase->stream.out;
1147 if (out && out->compr)
1148 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1149 }
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301150
1151 if (usecase->type == PCM_CAPTURE) {
1152 in = usecase->stream.in;
1153 if (in && is_loopback_input_device(in->device)) {
1154 ALOGD("%s: set custom mtmx params v1", __func__);
1155 audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
1156 }
1157 } else {
1158 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
1159 }
Manish Dewangan58229382017-02-02 15:48:41 +05301160
Andy Hung756ecc12018-10-19 17:47:12 -07001161 // we shouldn't truncate mixer_path
1162 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1163 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1164 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001165 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001166 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301167 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1168 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1169 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1170 if (parms) {
1171 audio_extn_fm_set_parameters(adev, parms);
1172 str_parms_destroy(parms);
1173 }
1174 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001175 ALOGV("%s: exit", __func__);
1176 return 0;
1177}
1178
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001179int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001180 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001181{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001182 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001183 char mixer_path[MIXER_PATH_MAX_LENGTH];
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301184 struct stream_in *in = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001185
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301186 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001187 return -EINVAL;
1188
1189 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301190 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001191 snd_device = usecase->in_snd_device;
1192 else
1193 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001194 // we shouldn't truncate mixer_path
1195 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1196 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1197 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001198 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001199 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001200 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001201 if (usecase->type == PCM_CAPTURE) {
1202 struct stream_in *in = usecase->stream.in;
1203 if (in && in->ec_opened) {
1204 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
1205 in->ec_opened = false;
1206 }
1207 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001208 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301209 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301210
1211 if (usecase->type == PCM_CAPTURE) {
1212 in = usecase->stream.in;
1213 if (in && is_loopback_input_device(in->device)) {
1214 ALOGD("%s: reset custom mtmx params v1", __func__);
1215 audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
1216 }
1217 } else {
1218 audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
1219 }
1220
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001221 if ((usecase->type == PCM_PLAYBACK) &&
1222 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301223 usecase->stream.out->pspd_coeff_sent = false;
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05301224
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001225 ALOGV("%s: exit", __func__);
1226 return 0;
1227}
1228
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001229int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001230 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001231{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301232 int i, num_devices = 0;
1233 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001234 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1235
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001236 if (snd_device < SND_DEVICE_MIN ||
1237 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001238 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001239 return -EINVAL;
1240 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001241
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001242 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001243 ALOGE("%s: Invalid sound device returned", __func__);
1244 return -EINVAL;
1245 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001246
1247 adev->snd_dev_ref_cnt[snd_device]++;
1248
1249 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1250 (platform_split_snd_device(adev->platform,
1251 snd_device,
1252 &num_devices,
1253 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001254 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001255 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001256 return 0;
1257 }
1258
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001259 if (audio_extn_spkr_prot_is_enabled())
1260 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001261
Aalique Grahame22e49102018-12-18 14:23:57 -08001262 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1263
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001264 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1265 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001266 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1267 goto err;
1268 }
1269 audio_extn_dev_arbi_acquire(snd_device);
1270 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001271 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001272 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001273 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001274 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001275 } else if (platform_split_snd_device(adev->platform,
1276 snd_device,
1277 &num_devices,
1278 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301279 for (i = 0; i < num_devices; i++) {
1280 enable_snd_device(adev, new_snd_devices[i]);
1281 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001282 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001283 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001284 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301285
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301286
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001287 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1288 (audio_extn_a2dp_start_playback() < 0)) {
1289 ALOGE(" fail to configure A2dp Source control path ");
1290 goto err;
1291 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001292
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001293 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1294 (audio_extn_a2dp_start_capture() < 0)) {
1295 ALOGE(" fail to configure A2dp Sink control path ");
1296 goto err;
1297 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301298
Zhou Song12c29502019-03-16 10:37:18 +08001299 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1300 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1301 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1302 (audio_extn_sco_start_configuration() < 0)) {
1303 ALOGE(" fail to configure sco control path ");
1304 goto err;
1305 }
1306
Zhou Song4721e282019-08-26 14:16:12 +08001307 configure_btsco_sample_rate(snd_device);
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001308 /* due to the possibility of calibration overwrite between listen
1309 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001310 audio_extn_sound_trigger_update_device_status(snd_device,
1311 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301312 audio_extn_listen_update_device_status(snd_device,
1313 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001314 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001315 audio_extn_sound_trigger_update_device_status(snd_device,
1316 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301317 audio_extn_listen_update_device_status(snd_device,
1318 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001319 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001320 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001321 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001322 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301323
1324 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1325 !adev->native_playback_enabled &&
1326 audio_is_true_native_stream_active(adev)) {
1327 ALOGD("%s: %d: napb: enabling native mode in hardware",
1328 __func__, __LINE__);
1329 audio_route_apply_and_update_path(adev->audio_route,
1330 "true-native-mode");
1331 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301332 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301333 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1334 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001335 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001336 ALOGD("%s: init ec ref loopback", __func__);
1337 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1338 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001339 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001340 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001341err:
1342 adev->snd_dev_ref_cnt[snd_device]--;
1343 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344}
1345
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001346int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001347 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001348{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301349 int i, num_devices = 0;
1350 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001351 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1352
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001353 if (snd_device < SND_DEVICE_MIN ||
1354 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001355 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001356 return -EINVAL;
1357 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001358
1359 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1360 ALOGE("%s: Invalid sound device returned", __func__);
1361 return -EINVAL;
1362 }
1363
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001364 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1365 ALOGE("%s: device ref cnt is already 0", __func__);
1366 return -EINVAL;
1367 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001368
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001369 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001370
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001371
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001372 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001373 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301374
Aalique Grahame22e49102018-12-18 14:23:57 -08001375 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1376
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001377 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1378 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001379 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001380
1381 // when speaker device is disabled, reset swap.
1382 // will be renabled on usecase start
1383 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001384 } else if (platform_split_snd_device(adev->platform,
1385 snd_device,
1386 &num_devices,
1387 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301388 for (i = 0; i < num_devices; i++) {
1389 disable_snd_device(adev, new_snd_devices[i]);
1390 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001391 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001392 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001393 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001394 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001395
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001396 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301397 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001398 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001399 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001400 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001401 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301402 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001403 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301404 adev->native_playback_enabled) {
1405 ALOGD("%s: %d: napb: disabling native mode in hardware",
1406 __func__, __LINE__);
1407 audio_route_reset_and_update_path(adev->audio_route,
1408 "true-native-mode");
1409 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001410 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301411 adev->asrc_mode_enabled) {
1412 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301413 disable_asrc_mode(adev);
1414 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001415 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301416 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001417 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001418 ALOGD("%s: deinit ec ref loopback", __func__);
1419 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1420 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001421
1422 audio_extn_utils_release_snd_device(snd_device);
1423 } else {
1424 if (platform_split_snd_device(adev->platform,
1425 snd_device,
1426 &num_devices,
1427 new_snd_devices) == 0) {
1428 for (i = 0; i < num_devices; i++) {
1429 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1430 }
1431 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001432 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001434 return 0;
1435}
1436
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001437/*
1438 legend:
1439 uc - existing usecase
1440 new_uc - new usecase
1441 d1, d11, d2 - SND_DEVICE enums
1442 a1, a2 - corresponding ANDROID device enums
1443 B1, B2 - backend strings
1444
1445case 1
1446 uc->dev d1 (a1) B1
1447 new_uc->dev d1 (a1), d2 (a2) B1, B2
1448
1449 resolution: disable and enable uc->dev on d1
1450
1451case 2
1452 uc->dev d1 (a1) B1
1453 new_uc->dev d11 (a1) B1
1454
1455 resolution: need to switch uc since d1 and d11 are related
1456 (e.g. speaker and voice-speaker)
1457 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1458
1459case 3
1460 uc->dev d1 (a1) B1
1461 new_uc->dev d2 (a2) B2
1462
1463 resolution: no need to switch uc
1464
1465case 4
1466 uc->dev d1 (a1) B1
1467 new_uc->dev d2 (a2) B1
1468
1469 resolution: disable enable uc-dev on d2 since backends match
1470 we cannot enable two streams on two different devices if they
1471 share the same backend. e.g. if offload is on speaker device using
1472 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1473 using the same backend, offload must also be switched to voice-handset.
1474
1475case 5
1476 uc->dev d1 (a1) B1
1477 new_uc->dev d1 (a1), d2 (a2) B1
1478
1479 resolution: disable enable uc-dev on d2 since backends match
1480 we cannot enable two streams on two different devices if they
1481 share the same backend.
1482
1483case 6
1484 uc->dev d1 (a1) B1
1485 new_uc->dev d2 (a1) B2
1486
1487 resolution: no need to switch
1488
1489case 7
1490 uc->dev d1 (a1), d2 (a2) B1, B2
1491 new_uc->dev d1 (a1) B1
1492
1493 resolution: no need to switch
1494
Zhou Song4ba65882018-07-09 14:48:07 +08001495case 8
1496 uc->dev d1 (a1) B1
1497 new_uc->dev d11 (a1), d2 (a2) B1, B2
1498 resolution: compared to case 1, for this case, d1 and d11 are related
1499 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001500*/
1501static snd_device_t derive_playback_snd_device(void * platform,
1502 struct audio_usecase *uc,
1503 struct audio_usecase *new_uc,
1504 snd_device_t new_snd_device)
1505{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301506 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001507
1508 snd_device_t d1 = uc->out_snd_device;
1509 snd_device_t d2 = new_snd_device;
1510
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301511 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301512 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301513 a1 = uc->stream.inout->out_config.devices;
1514 a2 = new_uc->stream.inout->out_config.devices;
1515 break;
1516 default :
1517 a1 = uc->stream.out->devices;
1518 a2 = new_uc->stream.out->devices;
1519 break;
1520 }
1521
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001522 // Treat as a special case when a1 and a2 are not disjoint
1523 if ((a1 != a2) && (a1 & a2)) {
1524 snd_device_t d3[2];
1525 int num_devices = 0;
1526 int ret = platform_split_snd_device(platform,
1527 popcount(a1) > 1 ? d1 : d2,
1528 &num_devices,
1529 d3);
1530 if (ret < 0) {
1531 if (ret != -ENOSYS) {
1532 ALOGW("%s failed to split snd_device %d",
1533 __func__,
1534 popcount(a1) > 1 ? d1 : d2);
1535 }
1536 goto end;
1537 }
1538
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001539 if (platform_check_backends_match(d3[0], d3[1])) {
1540 return d2; // case 5
1541 } else {
Samyak Jaind826b502019-07-17 16:16:42 +05301542 if (popcount(a1) > 1)
1543 return d1; //case 7
Garmond Leungb9eeba42018-09-18 11:10:41 -07001544 // check if d1 is related to any of d3's
1545 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001546 return d1; // case 1
1547 else
1548 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001549 }
1550 } else {
1551 if (platform_check_backends_match(d1, d2)) {
1552 return d2; // case 2, 4
1553 } else {
1554 return d1; // case 6, 3
1555 }
1556 }
1557
1558end:
1559 return d2; // return whatever was calculated before.
1560}
1561
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001562static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301563 struct audio_usecase *uc_info,
1564 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001565{
1566 struct listnode *node;
1567 struct audio_usecase *usecase;
1568 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301569 snd_device_t uc_derive_snd_device;
1570 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001571 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1572 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001573 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301574 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001575 /*
1576 * This function is to make sure that all the usecases that are active on
1577 * the hardware codec backend are always routed to any one device that is
1578 * handled by the hardware codec.
1579 * For example, if low-latency and deep-buffer usecases are currently active
1580 * on speaker and out_set_parameters(headset) is received on low-latency
1581 * output, then we have to make sure deep-buffer is also switched to headset,
1582 * because of the limitation that both the devices cannot be enabled
1583 * at the same time as they share the same backend.
1584 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001585 /*
1586 * This call is to check if we need to force routing for a particular stream
1587 * If there is a backend configuration change for the device when a
1588 * new stream starts, then ADM needs to be closed and re-opened with the new
1589 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001590 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001591 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001592 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1593 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301594 /* For a2dp device reconfigure all active sessions
1595 * with new AFE encoder format based on a2dp state
1596 */
1597 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1598 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1599 audio_extn_a2dp_is_force_device_switch()) {
1600 force_routing = true;
1601 force_restart_session = true;
1602 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301603 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1604
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001606 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001607 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001608 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1609 switch_device[i] = false;
1610
1611 list_for_each(node, &adev->usecase_list) {
1612 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001613
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301614 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1615 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301616 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301617 platform_get_snd_device_name(usecase->out_snd_device),
1618 platform_check_backends_match(snd_device, usecase->out_snd_device));
Rahul Sharma99770982019-03-06 17:05:26 +05301619 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info) &&
1620 (usecase->type != PCM_PASSTHROUGH)) {
Ashish Jain6a65b352017-03-21 17:24:40 +05301621 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1622 usecase, uc_info, snd_device);
1623 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1624 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1625 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1626 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001627 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301628 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1629 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1630 ((force_restart_session) ||
1631 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301632 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1633 __func__, use_case_table[usecase->id],
1634 platform_get_snd_device_name(usecase->out_snd_device));
1635 disable_audio_route(adev, usecase);
1636 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301637 /* Enable existing usecase on derived playback device */
1638 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301639 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301640 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001641 }
1642 }
1643
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301644 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1645 num_uc_to_switch);
1646
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001647 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001648 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001649
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301650 /* Make sure the previous devices to be disabled first and then enable the
1651 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 list_for_each(node, &adev->usecase_list) {
1653 usecase = node_to_item(node, struct audio_usecase, list);
1654 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001655 /* Check if output sound device to be switched can be split and if any
1656 of the split devices match with derived sound device */
1657 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1658 &num_devices, split_snd_devices) == 0) {
1659 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1660 for (i = 0; i < num_devices; i++) {
1661 /* Disable devices that do not match with derived sound device */
1662 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1663 disable_snd_device(adev, split_snd_devices[i]);
1664 }
1665 } else {
1666 disable_snd_device(adev, usecase->out_snd_device);
1667 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001668 }
1669 }
1670
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001671 list_for_each(node, &adev->usecase_list) {
1672 usecase = node_to_item(node, struct audio_usecase, list);
1673 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001674 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1675 &num_devices, split_snd_devices) == 0) {
1676 /* Enable derived sound device only if it does not match with
1677 one of the split sound devices. This is because the matching
1678 sound device was not disabled */
1679 bool should_enable = true;
1680 for (i = 0; i < num_devices; i++) {
1681 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1682 should_enable = false;
1683 break;
1684 }
1685 }
1686 if (should_enable)
1687 enable_snd_device(adev, derive_snd_device[usecase->id]);
1688 } else {
1689 enable_snd_device(adev, derive_snd_device[usecase->id]);
1690 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001691 }
1692 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001693
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001694 /* Re-route all the usecases on the shared backend other than the
1695 specified usecase to new snd devices */
1696 list_for_each(node, &adev->usecase_list) {
1697 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301698 /* Update the out_snd_device only before enabling the audio route */
1699 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301700 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301701 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301702 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301703 use_case_table[usecase->id],
1704 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001705 /* Update voc calibration before enabling VoIP route */
1706 if (usecase->type == VOIP_CALL)
1707 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001708 usecase->out_snd_device,
1709 platform_get_input_snd_device(
1710 adev->platform, NULL,
1711 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301712 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301713 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001714 out_set_voip_volume(&usecase->stream.out->stream,
1715 usecase->stream.out->volume_l,
1716 usecase->stream.out->volume_r);
1717 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301718 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001719 }
1720 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001721 }
1722}
1723
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301724static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001725 struct audio_usecase *uc_info,
1726 snd_device_t snd_device)
1727{
1728 struct listnode *node;
1729 struct audio_usecase *usecase;
1730 bool switch_device[AUDIO_USECASE_MAX];
1731 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301732 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001733 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001734
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301735 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1736 snd_device);
1737 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301738
1739 /*
1740 * Make sure out devices is checked against out codec backend device and
1741 * also in devices against in codec backend. Checking out device against in
1742 * codec backend or vice versa causes issues.
1743 */
1744 if (uc_info->type == PCM_CAPTURE)
1745 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001746 /*
1747 * This function is to make sure that all the active capture usecases
1748 * are always routed to the same input sound device.
1749 * For example, if audio-record and voice-call usecases are currently
1750 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1751 * is received for voice call then we have to make sure that audio-record
1752 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1753 * because of the limitation that two devices cannot be enabled
1754 * at the same time if they share the same backend.
1755 */
1756 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1757 switch_device[i] = false;
1758
1759 list_for_each(node, &adev->usecase_list) {
1760 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301761 /*
1762 * TODO: Enhance below condition to handle BT sco/USB multi recording
1763 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001764 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001765 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301766 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301767 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301768 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301769 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001770 ((uc_info->type == VOICE_CALL &&
1771 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1772 platform_check_backends_match(snd_device,\
1773 usecase->in_snd_device)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001774 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001775 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1776 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001777 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001778 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001779 switch_device[usecase->id] = true;
1780 num_uc_to_switch++;
1781 }
1782 }
1783
1784 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001785 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001786
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301787 /* Make sure the previous devices to be disabled first and then enable the
1788 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001789 list_for_each(node, &adev->usecase_list) {
1790 usecase = node_to_item(node, struct audio_usecase, list);
1791 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001792 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001793 }
1794 }
1795
1796 list_for_each(node, &adev->usecase_list) {
1797 usecase = node_to_item(node, struct audio_usecase, list);
1798 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001799 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001800 }
1801 }
1802
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001803 /* Re-route all the usecases on the shared backend other than the
1804 specified usecase to new snd devices */
1805 list_for_each(node, &adev->usecase_list) {
1806 usecase = node_to_item(node, struct audio_usecase, list);
1807 /* Update the in_snd_device only before enabling the audio route */
1808 if (switch_device[usecase->id] ) {
1809 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001810 if (usecase->type != VOICE_CALL) {
1811 /* Update voc calibration before enabling VoIP route */
1812 if (usecase->type == VOIP_CALL)
1813 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001814 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001815 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301816 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001817 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001818 }
1819 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001820 }
1821}
1822
Mingming Yin3a941d42016-02-17 18:08:05 -08001823static void reset_hdmi_sink_caps(struct stream_out *out) {
1824 int i = 0;
1825
1826 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1827 out->supported_channel_masks[i] = 0;
1828 }
1829 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1830 out->supported_formats[i] = 0;
1831 }
1832 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1833 out->supported_sample_rates[i] = 0;
1834 }
1835}
1836
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001837/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001838static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839{
Mingming Yin3a941d42016-02-17 18:08:05 -08001840 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001841 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001842
Mingming Yin3a941d42016-02-17 18:08:05 -08001843 reset_hdmi_sink_caps(out);
1844
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001845 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001846 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001847 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001848 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001849 }
1850
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001851 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001852 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001853 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001854 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001855 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1856 case 6:
1857 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1858 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1859 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1860 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1861 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1862 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001863 break;
1864 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001865 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001866 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001867 break;
1868 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001869
1870 // check channel format caps
1871 i = 0;
1872 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1873 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1874 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1875 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1876 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1877 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1878 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1879 }
1880
Ben Romberger1aaaf862017-04-06 17:49:46 -07001881 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1882 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1883 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1884 }
1885
Mingming Yin3a941d42016-02-17 18:08:05 -08001886 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1887 ALOGV(":%s HDMI supports DTS format", __func__);
1888 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1889 }
1890
1891 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1892 ALOGV(":%s HDMI supports DTS HD format", __func__);
1893 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1894 }
1895
Naresh Tanniru928f0862017-04-07 16:44:23 -07001896 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1897 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1898 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1899 }
1900
Mingming Yin3a941d42016-02-17 18:08:05 -08001901
1902 // check sample rate caps
1903 i = 0;
1904 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1905 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1906 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1907 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1908 }
1909 }
1910
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001911 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001912}
1913
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001914static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1915 uint32_t *supported_sample_rates __unused,
1916 uint32_t max_rates __unused)
1917{
1918 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1919 supported_sample_rates,
1920 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301921 ssize_t i = 0;
1922
1923 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001924 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1925 supported_sample_rates[i]);
1926 }
1927 return count;
1928}
1929
1930static inline int read_usb_sup_channel_masks(bool is_playback,
1931 audio_channel_mask_t *supported_channel_masks,
1932 uint32_t max_masks)
1933{
1934 int channels = audio_extn_usb_get_max_channels(is_playback);
1935 int channel_count;
1936 uint32_t num_masks = 0;
1937 if (channels > MAX_HIFI_CHANNEL_COUNT)
1938 channels = MAX_HIFI_CHANNEL_COUNT;
1939
1940 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001941 // start from 2 channels as framework currently doesn't support mono.
1942 if (channels >= FCC_2) {
1943 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1944 }
1945 for (channel_count = FCC_2;
1946 channel_count <= channels && num_masks < max_masks;
1947 ++channel_count) {
1948 supported_channel_masks[num_masks++] =
1949 audio_channel_mask_for_index_assignment_from_count(channel_count);
1950 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001951 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001952 // For capture we report all supported channel masks from 1 channel up.
1953 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001954 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1955 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001956 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1957 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1958 if (channel_count <= FCC_2) {
1959 mask = audio_channel_in_mask_from_count(channel_count);
1960 supported_channel_masks[num_masks++] = mask;
1961 }
1962 const audio_channel_mask_t index_mask =
1963 audio_channel_mask_for_index_assignment_from_count(channel_count);
1964 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1965 supported_channel_masks[num_masks++] = index_mask;
1966 }
1967 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001968 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301969
vincenttewf51c94e2019-05-07 10:28:53 +08001970 for (size_t i = 0; i < num_masks; ++i) {
1971 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1972 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301973 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001974 return num_masks;
1975}
1976
1977static inline int read_usb_sup_formats(bool is_playback __unused,
1978 audio_format_t *supported_formats,
1979 uint32_t max_formats __unused)
1980{
1981 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1982 switch (bitwidth) {
1983 case 24:
1984 // XXX : usb.c returns 24 for s24 and s24_le?
1985 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1986 break;
1987 case 32:
1988 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1989 break;
1990 case 16:
1991 default :
1992 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1993 break;
1994 }
1995 ALOGV("%s: %s supported format %d", __func__,
1996 is_playback ? "P" : "C", bitwidth);
1997 return 1;
1998}
1999
2000static inline int read_usb_sup_params_and_compare(bool is_playback,
2001 audio_format_t *format,
2002 audio_format_t *supported_formats,
2003 uint32_t max_formats,
2004 audio_channel_mask_t *mask,
2005 audio_channel_mask_t *supported_channel_masks,
2006 uint32_t max_masks,
2007 uint32_t *rate,
2008 uint32_t *supported_sample_rates,
2009 uint32_t max_rates) {
2010 int ret = 0;
2011 int num_formats;
2012 int num_masks;
2013 int num_rates;
2014 int i;
2015
2016 num_formats = read_usb_sup_formats(is_playback, supported_formats,
2017 max_formats);
2018 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
2019 max_masks);
2020
2021 num_rates = read_usb_sup_sample_rates(is_playback,
2022 supported_sample_rates, max_rates);
2023
2024#define LUT(table, len, what, dflt) \
2025 for (i=0; i<len && (table[i] != what); i++); \
2026 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
2027
2028 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2029 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2030 LUT(supported_sample_rates, num_rates, *rate, 0);
2031
2032#undef LUT
2033 return ret < 0 ? -EINVAL : 0; // HACK TBD
2034}
2035
Alexy Josephb1379942016-01-29 15:49:38 -08002036audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002037 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002038{
2039 struct audio_usecase *usecase;
2040 struct listnode *node;
2041
2042 list_for_each(node, &adev->usecase_list) {
2043 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002044 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002045 ALOGV("%s: usecase id %d", __func__, usecase->id);
2046 return usecase->id;
2047 }
2048 }
2049 return USECASE_INVALID;
2050}
2051
Alexy Josephb1379942016-01-29 15:49:38 -08002052struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002053 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002054{
2055 struct audio_usecase *usecase;
2056 struct listnode *node;
2057
2058 list_for_each(node, &adev->usecase_list) {
2059 usecase = node_to_item(node, struct audio_usecase, list);
2060 if (usecase->id == uc_id)
2061 return usecase;
2062 }
2063 return NULL;
2064}
2065
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302066/*
2067 * is a true native playback active
2068 */
2069bool audio_is_true_native_stream_active(struct audio_device *adev)
2070{
2071 bool active = false;
2072 int i = 0;
2073 struct listnode *node;
2074
2075 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2076 ALOGV("%s:napb: not in true mode or non hdphones device",
2077 __func__);
2078 active = false;
2079 goto exit;
2080 }
2081
2082 list_for_each(node, &adev->usecase_list) {
2083 struct audio_usecase *uc;
2084 uc = node_to_item(node, struct audio_usecase, list);
2085 struct stream_out *curr_out =
2086 (struct stream_out*) uc->stream.out;
2087
2088 if (curr_out && PCM_PLAYBACK == uc->type) {
2089 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2090 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2091 uc->id, curr_out->sample_rate,
2092 curr_out->bit_width,
2093 platform_get_snd_device_name(uc->out_snd_device));
2094
2095 if (is_offload_usecase(uc->id) &&
2096 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2097 active = true;
2098 ALOGD("%s:napb:native stream detected", __func__);
2099 }
2100 }
2101 }
2102exit:
2103 return active;
2104}
2105
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002106uint32_t adev_get_dsp_bit_width_enforce_mode()
2107{
2108 if (adev == NULL) {
2109 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2110 return 0;
2111 }
2112 return adev->dsp_bit_width_enforce_mode;
2113}
2114
2115static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2116{
2117 char value[PROPERTY_VALUE_MAX];
2118 int trial;
2119 uint32_t dsp_bit_width_enforce_mode = 0;
2120
2121 if (!mixer) {
2122 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2123 __func__);
2124 return 0;
2125 }
2126
2127 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2128 value, NULL) > 0) {
2129 trial = atoi(value);
2130 switch (trial) {
2131 case 16:
2132 dsp_bit_width_enforce_mode = 16;
2133 break;
2134 case 24:
2135 dsp_bit_width_enforce_mode = 24;
2136 break;
2137 case 32:
2138 dsp_bit_width_enforce_mode = 32;
2139 break;
2140 default:
2141 dsp_bit_width_enforce_mode = 0;
2142 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2143 break;
2144 }
2145 }
2146
2147 return dsp_bit_width_enforce_mode;
2148}
2149
2150static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2151 uint32_t enforce_mode,
2152 bool enable)
2153{
2154 struct mixer_ctl *ctl = NULL;
2155 const char *mixer_ctl_name = "ASM Bit Width";
2156 uint32_t asm_bit_width_mode = 0;
2157
2158 if (enforce_mode == 0) {
2159 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2160 return;
2161 }
2162
2163 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2164 if (!ctl) {
2165 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2166 __func__, mixer_ctl_name);
2167 return;
2168 }
2169
2170 if (enable)
2171 asm_bit_width_mode = enforce_mode;
2172 else
2173 asm_bit_width_mode = 0;
2174
2175 ALOGV("%s DSP bit width feature status is %d width=%d",
2176 __func__, enable, asm_bit_width_mode);
2177 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2178 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2179 asm_bit_width_mode);
2180
2181 return;
2182}
2183
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302184/*
2185 * if native DSD playback active
2186 */
2187bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2188{
2189 bool active = false;
2190 struct listnode *node = NULL;
2191 struct audio_usecase *uc = NULL;
2192 struct stream_out *curr_out = NULL;
2193
2194 list_for_each(node, &adev->usecase_list) {
2195 uc = node_to_item(node, struct audio_usecase, list);
2196 curr_out = (struct stream_out*) uc->stream.out;
2197
2198 if (curr_out && PCM_PLAYBACK == uc->type &&
2199 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2200 active = true;
2201 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302202 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302203 }
2204 }
2205 return active;
2206}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302207
2208static bool force_device_switch(struct audio_usecase *usecase)
2209{
2210 bool ret = false;
2211 bool is_it_true_mode = false;
2212
Zhou Song30f2c3e2018-02-08 14:02:15 +08002213 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302214 usecase->type == TRANSCODE_LOOPBACK_RX ||
2215 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002216 return false;
2217 }
2218
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002219 if(usecase->stream.out == NULL) {
2220 ALOGE("%s: stream.out is NULL", __func__);
2221 return false;
2222 }
2223
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302224 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002225 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2226 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2227 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302228 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2229 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2230 (!is_it_true_mode && adev->native_playback_enabled)){
2231 ret = true;
2232 ALOGD("napb: time to toggle native mode");
2233 }
2234 }
2235
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302236 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302237 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2238 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002239 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302240 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302241 ALOGD("Force a2dp device switch to update new encoder config");
2242 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002243 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302244
Florian Pfister1a84f312018-07-19 14:38:18 +02002245 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302246 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2247 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002248 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302249 return ret;
2250}
2251
Aalique Grahame22e49102018-12-18 14:23:57 -08002252static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2253{
2254 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2255}
2256
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302257bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2258{
2259 bool ret=false;
2260 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2261 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2262 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2263 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2264 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2265 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2266 ret = true;
2267
2268 return ret;
2269}
2270
2271bool is_a2dp_device(snd_device_t out_snd_device)
2272{
2273 bool ret=false;
2274 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2275 ret = true;
2276
2277 return ret;
2278}
2279
2280bool is_bt_soc_on(struct audio_device *adev)
2281{
2282 struct mixer_ctl *ctl;
2283 char *mixer_ctl_name = "BT SOC status";
2284 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2285 bool bt_soc_status = true;
2286 if (!ctl) {
2287 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2288 __func__, mixer_ctl_name);
2289 /*This is to ensure we dont break targets which dont have the kernel change*/
2290 return true;
2291 }
2292 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2293 ALOGD("BT SOC status: %d",bt_soc_status);
2294 return bt_soc_status;
2295}
2296
Zhou Song4721e282019-08-26 14:16:12 +08002297static int configure_btsco_sample_rate(snd_device_t snd_device)
2298{
2299 struct mixer_ctl *ctl = NULL;
2300 struct mixer_ctl *ctl_sr_rx = NULL, *ctl_sr_tx = NULL, *ctl_sr = NULL;
2301 char *rate_str = NULL;
2302 bool is_rx_dev = true;
2303
2304 if (is_btsco_device(snd_device, snd_device)) {
2305 ctl_sr_tx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate TX");
2306 ctl_sr_rx = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate RX");
2307 if (!ctl_sr_tx || !ctl_sr_rx) {
2308 ctl_sr = mixer_get_ctl_by_name(adev->mixer, "BT SampleRate");
2309 if (!ctl_sr)
2310 return -ENOSYS;
2311 }
2312
2313 switch (snd_device) {
2314 case SND_DEVICE_OUT_BT_SCO:
2315 rate_str = "KHZ_8";
2316 break;
2317 case SND_DEVICE_IN_BT_SCO_MIC_NREC:
2318 case SND_DEVICE_IN_BT_SCO_MIC:
2319 rate_str = "KHZ_8";
2320 is_rx_dev = false;
2321 break;
2322 case SND_DEVICE_OUT_BT_SCO_WB:
2323 rate_str = "KHZ_16";
2324 break;
2325 case SND_DEVICE_IN_BT_SCO_MIC_WB_NREC:
2326 case SND_DEVICE_IN_BT_SCO_MIC_WB:
2327 rate_str = "KHZ_16";
2328 is_rx_dev = false;
2329 break;
2330 default:
2331 return 0;
2332 }
2333
2334 ctl = (ctl_sr == NULL) ? (is_rx_dev ? ctl_sr_rx : ctl_sr_tx) : ctl_sr;
2335 if (mixer_ctl_set_enum_by_string(ctl, rate_str) != 0)
2336 return -ENOSYS;
2337 }
2338 return 0;
2339}
2340
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302341int out_standby_l(struct audio_stream *stream);
2342
Eric Laurent637e2d42018-11-15 12:24:31 -08002343struct stream_in *adev_get_active_input(const struct audio_device *adev)
2344{
2345 struct listnode *node;
2346 struct stream_in *last_active_in = NULL;
2347
2348 /* Get last added active input.
2349 * TODO: We may use a priority mechanism to pick highest priority active source */
2350 list_for_each(node, &adev->usecase_list)
2351 {
2352 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2353 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2354 last_active_in = usecase->stream.in;
2355 }
2356
2357 return last_active_in;
2358}
2359
2360struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2361{
2362 struct listnode *node;
2363
2364 /* First check active inputs with voice communication source and then
2365 * any input if audio mode is in communication */
2366 list_for_each(node, &adev->usecase_list)
2367 {
2368 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2369 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2370 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2371 return usecase->stream.in;
2372 }
2373 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2374 return adev_get_active_input(adev);
2375
2376 return NULL;
2377}
2378
Carter Hsu2e429db2019-05-14 18:50:52 +08002379/*
2380 * Aligned with policy.h
2381 */
2382static inline int source_priority(int inputSource)
2383{
2384 switch (inputSource) {
2385 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2386 return 9;
2387 case AUDIO_SOURCE_CAMCORDER:
2388 return 8;
2389 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2390 return 7;
2391 case AUDIO_SOURCE_UNPROCESSED:
2392 return 6;
2393 case AUDIO_SOURCE_MIC:
2394 return 5;
2395 case AUDIO_SOURCE_ECHO_REFERENCE:
2396 return 4;
2397 case AUDIO_SOURCE_FM_TUNER:
2398 return 3;
2399 case AUDIO_SOURCE_VOICE_RECOGNITION:
2400 return 2;
2401 case AUDIO_SOURCE_HOTWORD:
2402 return 1;
2403 default:
2404 break;
2405 }
2406 return 0;
2407}
2408
2409static struct stream_in *get_priority_input(struct audio_device *adev)
2410{
2411 struct listnode *node;
2412 struct audio_usecase *usecase;
2413 int last_priority = 0, priority;
2414 struct stream_in *priority_in = NULL;
2415 struct stream_in *in;
2416
2417 list_for_each(node, &adev->usecase_list) {
2418 usecase = node_to_item(node, struct audio_usecase, list);
2419 if (usecase->type == PCM_CAPTURE) {
2420 in = usecase->stream.in;
2421 if (!in)
2422 continue;
2423 priority = source_priority(in->source);
2424
2425 if (priority > last_priority) {
2426 last_priority = priority;
2427 priority_in = in;
2428 }
2429 }
2430 }
2431 return priority_in;
2432}
2433
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002434int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002435{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002436 snd_device_t out_snd_device = SND_DEVICE_NONE;
2437 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002438 struct audio_usecase *usecase = NULL;
2439 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002440 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002441 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302442 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002443 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002444 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002445
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302446 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2447
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002448 usecase = get_usecase_from_list(adev, uc_id);
2449 if (usecase == NULL) {
2450 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2451 return -EINVAL;
2452 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002453
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002454 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002455 (usecase->type == VOIP_CALL) ||
2456 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302457 if(usecase->stream.out == NULL) {
2458 ALOGE("%s: stream.out is NULL", __func__);
2459 return -EINVAL;
2460 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002461 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002462 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002463 in_snd_device = platform_get_input_snd_device(adev->platform,
2464 NULL,
2465 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002466 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302467 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302468 if (usecase->stream.inout == NULL) {
2469 ALOGE("%s: stream.inout is NULL", __func__);
2470 return -EINVAL;
2471 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302472 stream_out.devices = usecase->stream.inout->out_config.devices;
2473 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2474 stream_out.format = usecase->stream.inout->out_config.format;
2475 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2476 out_snd_device = platform_get_output_snd_device(adev->platform,
2477 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302478 usecase->devices = out_snd_device;
2479 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2480 if (usecase->stream.inout == NULL) {
2481 ALOGE("%s: stream.inout is NULL", __func__);
2482 return -EINVAL;
2483 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002484 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302485 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002486 } else {
2487 /*
2488 * If the voice call is active, use the sound devices of voice call usecase
2489 * so that it would not result any device switch. All the usecases will
2490 * be switched to new device when select_devices() is called for voice call
2491 * usecase. This is to avoid switching devices for voice call when
2492 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002493 * choose voice call device only if the use case device is
2494 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002495 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002496 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002497 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002498 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002499 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2500 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302501 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2502 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002503 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2504 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002505 in_snd_device = vc_usecase->in_snd_device;
2506 out_snd_device = vc_usecase->out_snd_device;
2507 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002508 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002509 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002510 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002511 if ((voip_usecase != NULL) &&
2512 (usecase->type == PCM_PLAYBACK) &&
2513 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002514 out_snd_device_backend_match = platform_check_backends_match(
2515 voip_usecase->out_snd_device,
2516 platform_get_output_snd_device(
2517 adev->platform,
2518 usecase->stream.out));
2519 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002520 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002521 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2522 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002523 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002524 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002525 in_snd_device = voip_usecase->in_snd_device;
2526 out_snd_device = voip_usecase->out_snd_device;
2527 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002528 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002529 hfp_ucid = audio_extn_hfp_get_usecase();
2530 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002531 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002532 in_snd_device = hfp_usecase->in_snd_device;
2533 out_snd_device = hfp_usecase->out_snd_device;
2534 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002535 }
2536 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302537 if (usecase->stream.out == NULL) {
2538 ALOGE("%s: stream.out is NULL", __func__);
2539 return -EINVAL;
2540 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002541 usecase->devices = usecase->stream.out->devices;
2542 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002543 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002544 struct stream_out *voip_out = adev->primary_output;
2545 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002546 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002547 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002548 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002549
Eric Laurent637e2d42018-11-15 12:24:31 -08002550 if (voip_usecase)
2551 voip_out = voip_usecase->stream.out;
2552
2553 if (usecase->stream.out == voip_out && voip_in != NULL)
2554 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002555 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002556 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302557 if (usecase->stream.in == NULL) {
2558 ALOGE("%s: stream.in is NULL", __func__);
2559 return -EINVAL;
2560 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002561 usecase->devices = usecase->stream.in->device;
2562 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002563 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002564 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002565 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002566 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002567
2568 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002569 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2570 USECASE_AUDIO_PLAYBACK_VOIP);
2571
Carter Hsu2e429db2019-05-14 18:50:52 +08002572 usecase->stream.in->enable_ec_port = false;
2573
Eric Laurent637e2d42018-11-15 12:24:31 -08002574 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2575 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2576 } else if (voip_usecase) {
2577 out_device = voip_usecase->stream.out->devices;
2578 } else if (adev->primary_output &&
2579 !adev->primary_output->standby) {
2580 out_device = adev->primary_output->devices;
2581 } else {
2582 /* forcing speaker o/p device to get matching i/p pair
2583 in case o/p is not routed from same primary HAL */
2584 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2585 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002586 priority_in = voip_in;
2587 } else {
2588 /* get the input with the highest priority source*/
2589 priority_in = get_priority_input(adev);
2590
2591 if (!priority_in)
2592 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002593 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002594
Eric Laurent637e2d42018-11-15 12:24:31 -08002595 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002596 priority_in,
Eric Laurent637e2d42018-11-15 12:24:31 -08002597 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002598 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002599 }
2600 }
2601
2602 if (out_snd_device == usecase->out_snd_device &&
2603 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302604
2605 if (!force_device_switch(usecase))
2606 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002607 }
2608
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302609 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002610 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302611 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2612 return 0;
2613 }
2614
Aalique Grahame22e49102018-12-18 14:23:57 -08002615 if (out_snd_device != SND_DEVICE_NONE &&
2616 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2617 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2618 __func__,
2619 use_case_table[uc_id],
2620 adev->last_logged_snd_device[uc_id][0],
2621 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2622 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2623 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2624 -1,
2625 out_snd_device,
2626 platform_get_snd_device_name(out_snd_device),
2627 platform_get_snd_device_acdb_id(out_snd_device));
2628 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2629 }
2630 if (in_snd_device != SND_DEVICE_NONE &&
2631 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2632 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2633 __func__,
2634 use_case_table[uc_id],
2635 adev->last_logged_snd_device[uc_id][1],
2636 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2637 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2638 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2639 -1,
2640 in_snd_device,
2641 platform_get_snd_device_name(in_snd_device),
2642 platform_get_snd_device_acdb_id(in_snd_device));
2643 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2644 }
2645
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647 /*
2648 * Limitation: While in call, to do a device switch we need to disable
2649 * and enable both RX and TX devices though one of them is same as current
2650 * device.
2651 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002652 if ((usecase->type == VOICE_CALL) &&
2653 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2654 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002655 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002656 }
2657
2658 if (((usecase->type == VOICE_CALL) ||
2659 (usecase->type == VOIP_CALL)) &&
2660 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2661 /* Disable sidetone only if voice/voip call already exists */
2662 if (voice_is_call_state_active(adev) ||
2663 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002664 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002665
2666 /* Disable aanc only if voice call exists */
2667 if (voice_is_call_state_active(adev))
2668 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002669 }
2670
Aalique Grahame22e49102018-12-18 14:23:57 -08002671 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2672 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002673 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302674 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002675 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2676 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2677 else
2678 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302679 }
2680
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002681 /* Disable current sound devices */
2682 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002683 disable_audio_route(adev, usecase);
2684 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 }
2686
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002687 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002688 disable_audio_route(adev, usecase);
2689 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 }
2691
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002692 /* Applicable only on the targets that has external modem.
2693 * New device information should be sent to modem before enabling
2694 * the devices to reduce in-call device switch time.
2695 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002696 if ((usecase->type == VOICE_CALL) &&
2697 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2698 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002699 status = platform_switch_voice_call_enable_device_config(adev->platform,
2700 out_snd_device,
2701 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002702 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002703
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002704 /* Enable new sound devices */
2705 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002706 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302707 if (platform_check_codec_asrc_support(adev->platform))
2708 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002709 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002710 }
2711
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002712 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302713 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002714 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002715 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002716
Avinash Vaish71a8b972014-07-24 15:36:33 +05302717 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002718 status = platform_switch_voice_call_device_post(adev->platform,
2719 out_snd_device,
2720 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302721 enable_audio_route_for_voice_usecases(adev, usecase);
2722 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002723
sangwoo170731f2013-06-08 15:36:36 +09002724 usecase->in_snd_device = in_snd_device;
2725 usecase->out_snd_device = out_snd_device;
2726
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302727 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2728 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302729 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002730 if ((24 == usecase->stream.out->bit_width) &&
2731 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2732 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2733 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2734 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2735 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2736 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2737 /*
2738 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2739 * configured device sample rate, if not update the COPP rate to be equal to the
2740 * device sample rate, else open COPP at stream sample rate
2741 */
2742 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2743 usecase->stream.out->sample_rate,
2744 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302745 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2746 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002747 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2748 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2749 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2750 }
Weiyin Jiangcdece202019-07-08 16:13:16 +08002751 }
2752 enable_audio_route(adev, usecase);
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002753
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002754 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002755
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002756 /* If input stream is already running then effect needs to be
2757 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002758 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002759 check_and_enable_effect(adev);
2760
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002761 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002762 /* Enable aanc only if voice call exists */
2763 if (voice_is_call_state_active(adev))
2764 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2765
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002766 /* Enable sidetone only if other voice/voip call already exists */
2767 if (voice_is_call_state_active(adev) ||
2768 voice_extn_compress_voip_is_started(adev))
2769 voice_set_sidetone(adev, out_snd_device, true);
2770 }
2771
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002772 /* Applicable only on the targets that has external modem.
2773 * Enable device command should be sent to modem only after
2774 * enabling voice call mixer controls
2775 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002776 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002777 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2778 out_snd_device,
2779 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302780
2781 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002782 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302783 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002784 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302785 if (is_bt_soc_on(adev) == false){
2786 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002787 if (in->pcm != NULL)
2788 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302789 }
2790 }
2791 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2792 && usecase->stream.out->started) {
2793 if (is_bt_soc_on(adev) == false) {
2794 ALOGD("BT SCO/A2DP disconnected while in connection");
2795 out_standby_l(&usecase->stream.out->stream.common);
2796 }
2797 }
2798 } else if ((usecase->stream.out != NULL) &&
2799 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302800 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2801 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302802 usecase->stream.out->started) {
2803 if (is_bt_soc_on(adev) == false) {
2804 ALOGD("BT SCO/A2dp disconnected while in connection");
2805 out_standby_l(&usecase->stream.out->stream.common);
2806 }
2807 }
2808 }
2809
Yung Ti Su70cb8242018-06-22 17:38:47 +08002810 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002811 struct stream_out *voip_out = voip_usecase->stream.out;
2812 audio_extn_utils_send_app_type_gain(adev,
2813 voip_out->app_type_cfg.app_type,
2814 &voip_out->app_type_cfg.gain[0]);
2815 }
2816
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302817 ALOGD("%s: done",__func__);
2818
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002819 return status;
2820}
2821
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002822static int stop_input_stream(struct stream_in *in)
2823{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302824 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002825 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302826
2827 if (in == NULL) {
2828 ALOGE("%s: stream_in ptr is NULL", __func__);
2829 return -EINVAL;
2830 }
2831
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002833 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002834
Eric Laurent994a6932013-07-17 11:51:42 -07002835 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002836 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002837 uc_info = get_usecase_from_list(adev, in->usecase);
2838 if (uc_info == NULL) {
2839 ALOGE("%s: Could not find the usecase (%d) in the list",
2840 __func__, in->usecase);
2841 return -EINVAL;
2842 }
2843
Carter Hsu2e429db2019-05-14 18:50:52 +08002844 priority_in = get_priority_input(adev);
2845
Derek Chenea197282019-01-07 17:35:01 -08002846 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2847 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002848
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002849 /* Close in-call recording streams */
2850 voice_check_and_stop_incall_rec_usecase(adev, in);
2851
Eric Laurent150dbfe2013-02-27 14:31:02 -08002852 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002853 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002854
2855 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002856 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002857
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05302858 if (is_loopback_input_device(in->device))
2859 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);
2860
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002861 list_remove(&uc_info->list);
2862 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863
Carter Hsu2e429db2019-05-14 18:50:52 +08002864 if (priority_in == in) {
2865 priority_in = get_priority_input(adev);
2866 if (priority_in)
2867 select_devices(adev, priority_in->usecase);
2868 }
2869
Vatsal Buchac09ae062018-11-14 13:25:08 +05302870 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002871 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002872 return ret;
2873}
2874
2875int start_input_stream(struct stream_in *in)
2876{
2877 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002878 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002879 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302880
2881 if (in == NULL) {
2882 ALOGE("%s: stream_in ptr is NULL", __func__);
2883 return -EINVAL;
2884 }
2885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002886 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002887 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002888 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002889
Mingming Yin2664a5b2015-09-03 10:53:11 -07002890 if (get_usecase_from_list(adev, usecase) == NULL)
2891 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302892 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2893 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002894
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302895 if (CARD_STATUS_OFFLINE == in->card_status||
2896 CARD_STATUS_OFFLINE == adev->card_status) {
2897 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302898 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302899 goto error_config;
2900 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302901
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302902 if (audio_is_bluetooth_sco_device(in->device)) {
2903 if (!adev->bt_sco_on) {
2904 ALOGE("%s: SCO profile is not ready, return error", __func__);
2905 ret = -EIO;
2906 goto error_config;
2907 }
2908 }
2909
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002910 /* Check if source matches incall recording usecase criteria */
2911 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2912 if (ret)
2913 goto error_config;
2914 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002915 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2916
2917 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2918 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2919 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002920 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002921 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002922
Eric Laurentb23d5282013-05-14 15:27:20 -07002923 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002924 if (in->pcm_device_id < 0) {
2925 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2926 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002927 ret = -EINVAL;
2928 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002929 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002930
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002931 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002932
2933 if (!uc_info) {
2934 ret = -ENOMEM;
2935 goto error_config;
2936 }
2937
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002938 uc_info->id = in->usecase;
2939 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002940 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002941 uc_info->devices = in->device;
2942 uc_info->in_snd_device = SND_DEVICE_NONE;
2943 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002944
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002945 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002946 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302947 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2948 adev->perf_lock_opts,
2949 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002950 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002951
Derek Chenea197282019-01-07 17:35:01 -08002952 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2953 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002954
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05302955 android_atomic_acquire_cas(true, false, &(in->capture_stopped));
2956
Haynes Mathew George16081042017-05-31 17:16:49 -07002957 if (audio_extn_cin_attached_usecase(in->usecase)) {
Manish Dewangan46e07982018-12-13 18:18:59 +05302958 ret = audio_extn_cin_open_input_stream(in);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302959 if (ret)
2960 goto error_open;
2961 else
2962 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002963 }
2964
Haynes Mathew George16081042017-05-31 17:16:49 -07002965 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002966 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002967 ALOGE("%s: pcm stream not ready", __func__);
2968 goto error_open;
2969 }
2970 ret = pcm_start(in->pcm);
2971 if (ret < 0) {
2972 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2973 goto error_open;
2974 }
2975 } else {
2976 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2977 unsigned int pcm_open_retry_count = 0;
2978
2979 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2980 flags |= PCM_MMAP | PCM_NOIRQ;
2981 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2982 } else if (in->realtime) {
2983 flags |= PCM_MMAP | PCM_NOIRQ;
2984 }
2985
Garmond Leunge2433c32017-09-28 21:51:22 -07002986 if (audio_extn_ffv_get_stream() == in) {
2987 ALOGD("%s: ffv stream, update pcm config", __func__);
2988 audio_extn_ffv_update_pcm_config(&config);
2989 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002990 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2991 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2992
2993 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002994 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002995 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002996 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002997 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302998 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302999 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
3000 adev->card_status = CARD_STATUS_OFFLINE;
3001 in->card_status = CARD_STATUS_OFFLINE;
3002 ret = -EIO;
3003 goto error_open;
3004 }
3005
Haynes Mathew George16081042017-05-31 17:16:49 -07003006 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
3007 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
3008 if (in->pcm != NULL) {
3009 pcm_close(in->pcm);
3010 in->pcm = NULL;
3011 }
3012 if (pcm_open_retry_count-- == 0) {
3013 ret = -EIO;
3014 goto error_open;
3015 }
3016 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3017 continue;
3018 }
3019 break;
3020 }
3021
3022 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003023 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07003024 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003025 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003026 if (ret < 0) {
3027 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3028 pcm_close(in->pcm);
3029 in->pcm = NULL;
3030 goto error_open;
3031 }
3032 register_in_stream(in);
3033 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003034 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07003035 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003036 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07003037 if (ret < 0) {
3038 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003039 pcm_close(in->pcm);
3040 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003041 goto error_open;
3042 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003043 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003044 }
3045
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003046 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07003047 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
3048 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07003049
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303050 if (is_loopback_input_device(in->device))
3051 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);
3052
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05303053done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003054 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303055 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003056 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303057 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003058 return ret;
3059
3060error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08003061 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303062 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003063 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08003064
Eric Laurentc8400632013-02-14 19:04:54 -08003065error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303066 /*
3067 * sleep 50ms to allow sufficient time for kernel
3068 * drivers to recover incases like SSR.
3069 */
3070 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003071 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05303072 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003073 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003074}
3075
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003076void lock_input_stream(struct stream_in *in)
3077{
3078 pthread_mutex_lock(&in->pre_lock);
3079 pthread_mutex_lock(&in->lock);
3080 pthread_mutex_unlock(&in->pre_lock);
3081}
3082
3083void lock_output_stream(struct stream_out *out)
3084{
3085 pthread_mutex_lock(&out->pre_lock);
3086 pthread_mutex_lock(&out->lock);
3087 pthread_mutex_unlock(&out->pre_lock);
3088}
3089
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003090/* must be called with out->lock locked */
3091static int send_offload_cmd_l(struct stream_out* out, int command)
3092{
3093 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3094
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003095 if (!cmd) {
3096 ALOGE("failed to allocate mem for command 0x%x", command);
3097 return -ENOMEM;
3098 }
3099
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003100 ALOGVV("%s %d", __func__, command);
3101
3102 cmd->cmd = command;
3103 list_add_tail(&out->offload_cmd_list, &cmd->node);
3104 pthread_cond_signal(&out->offload_cond);
3105 return 0;
3106}
3107
3108/* must be called iwth out->lock locked */
3109static void stop_compressed_output_l(struct stream_out *out)
3110{
3111 out->offload_state = OFFLOAD_STATE_IDLE;
3112 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003113 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003114 if (out->compr != NULL) {
3115 compress_stop(out->compr);
3116 while (out->offload_thread_blocked) {
3117 pthread_cond_wait(&out->cond, &out->lock);
3118 }
3119 }
3120}
3121
Varun Balaraje49253e2017-07-06 19:48:56 +05303122bool is_interactive_usecase(audio_usecase_t uc_id)
3123{
3124 unsigned int i;
3125 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3126 if (uc_id == interactive_usecases[i])
3127 return true;
3128 }
3129 return false;
3130}
3131
3132static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3133{
3134 audio_usecase_t ret_uc = USECASE_INVALID;
3135 unsigned int intract_uc_index;
3136 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3137
3138 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3139 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3140 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3141 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3142 ret_uc = interactive_usecases[intract_uc_index];
3143 break;
3144 }
3145 }
3146
3147 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3148 return ret_uc;
3149}
3150
3151static void free_interactive_usecase(struct audio_device *adev,
3152 audio_usecase_t uc_id)
3153{
3154 unsigned int interact_uc_index;
3155 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3156
3157 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3158 if (interactive_usecases[interact_uc_index] == uc_id) {
3159 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3160 break;
3161 }
3162 }
3163 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3164}
3165
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003166bool is_offload_usecase(audio_usecase_t uc_id)
3167{
3168 unsigned int i;
3169 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3170 if (uc_id == offload_usecases[i])
3171 return true;
3172 }
3173 return false;
3174}
3175
Dhananjay Kumarac341582017-02-23 23:42:25 +05303176static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003177{
vivek mehta446c3962015-09-14 10:57:35 -07003178 audio_usecase_t ret_uc = USECASE_INVALID;
3179 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003180 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003181 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303182 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003183 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3184 else
3185 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003186
vivek mehta446c3962015-09-14 10:57:35 -07003187 pthread_mutex_lock(&adev->lock);
3188 if (get_usecase_from_list(adev, ret_uc) != NULL)
3189 ret_uc = USECASE_INVALID;
3190 pthread_mutex_unlock(&adev->lock);
3191
3192 return ret_uc;
3193 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003194
3195 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003196 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3197 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3198 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3199 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003200 break;
3201 }
3202 }
vivek mehta446c3962015-09-14 10:57:35 -07003203
3204 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3205 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003206}
3207
3208static void free_offload_usecase(struct audio_device *adev,
3209 audio_usecase_t uc_id)
3210{
vivek mehta446c3962015-09-14 10:57:35 -07003211 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003212 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003213
3214 if (!adev->multi_offload_enable)
3215 return;
3216
3217 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3218 if (offload_usecases[offload_uc_index] == uc_id) {
3219 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003220 break;
3221 }
3222 }
3223 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3224}
3225
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003226static void *offload_thread_loop(void *context)
3227{
3228 struct stream_out *out = (struct stream_out *) context;
3229 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003230 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003231
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003232 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003233 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003234 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3235
3236 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003237 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003238 out->offload_state = OFFLOAD_STATE_IDLE;
3239 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003240 for (;;) {
3241 struct offload_cmd *cmd = NULL;
3242 stream_callback_event_t event;
3243 bool send_callback = false;
3244
3245 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3246 __func__, list_empty(&out->offload_cmd_list),
3247 out->offload_state);
3248 if (list_empty(&out->offload_cmd_list)) {
3249 ALOGV("%s SLEEPING", __func__);
3250 pthread_cond_wait(&out->offload_cond, &out->lock);
3251 ALOGV("%s RUNNING", __func__);
3252 continue;
3253 }
3254
3255 item = list_head(&out->offload_cmd_list);
3256 cmd = node_to_item(item, struct offload_cmd, node);
3257 list_remove(item);
3258
3259 ALOGVV("%s STATE %d CMD %d out->compr %p",
3260 __func__, out->offload_state, cmd->cmd, out->compr);
3261
3262 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3263 free(cmd);
3264 break;
3265 }
3266
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003267 // allow OFFLOAD_CMD_ERROR reporting during standby
3268 // this is needed to handle failures during compress_open
3269 // Note however that on a pause timeout, the stream is closed
3270 // and no offload usecase will be active. Therefore this
3271 // special case is needed for compress_open failures alone
3272 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3273 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003274 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003275 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003276 pthread_cond_signal(&out->cond);
3277 continue;
3278 }
3279 out->offload_thread_blocked = true;
3280 pthread_mutex_unlock(&out->lock);
3281 send_callback = false;
3282 switch(cmd->cmd) {
3283 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003284 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003285 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003286 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003287 send_callback = true;
3288 event = STREAM_CBK_EVENT_WRITE_READY;
3289 break;
3290 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003291 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303292 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003293 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303294 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003295 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303296 if (ret < 0)
3297 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303298 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303299 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003300 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003301 else
3302 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003303 if (-ENETRESET != ret && !(-EINTR == ret &&
3304 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303305 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303306 pthread_mutex_lock(&out->lock);
3307 out->send_new_metadata = 1;
3308 out->send_next_track_params = true;
3309 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303310 event = STREAM_CBK_EVENT_DRAIN_READY;
3311 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3312 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303313 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003314 break;
3315 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003316 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003317 ret = compress_drain(out->compr);
3318 ALOGD("copl(%p):out of compress_drain", out);
3319 // EINTR check avoids drain interruption due to SSR
3320 if (-ENETRESET != ret && !(-EINTR == ret &&
3321 CARD_STATUS_OFFLINE == out->card_status)) {
3322 send_callback = true;
3323 event = STREAM_CBK_EVENT_DRAIN_READY;
3324 } else
3325 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003326 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303327 case OFFLOAD_CMD_ERROR:
3328 ALOGD("copl(%p): sending error callback to AF", out);
3329 send_callback = true;
3330 event = STREAM_CBK_EVENT_ERROR;
3331 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003332 default:
3333 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3334 break;
3335 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003336 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003337 out->offload_thread_blocked = false;
3338 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003339 if (send_callback && out->client_callback) {
3340 ALOGVV("%s: sending client_callback event %d", __func__, event);
3341 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003342 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003343 free(cmd);
3344 }
3345
3346 pthread_cond_signal(&out->cond);
3347 while (!list_empty(&out->offload_cmd_list)) {
3348 item = list_head(&out->offload_cmd_list);
3349 list_remove(item);
3350 free(node_to_item(item, struct offload_cmd, node));
3351 }
3352 pthread_mutex_unlock(&out->lock);
3353
3354 return NULL;
3355}
3356
3357static int create_offload_callback_thread(struct stream_out *out)
3358{
3359 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3360 list_init(&out->offload_cmd_list);
3361 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3362 offload_thread_loop, out);
3363 return 0;
3364}
3365
3366static int destroy_offload_callback_thread(struct stream_out *out)
3367{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003368 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003369 stop_compressed_output_l(out);
3370 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3371
3372 pthread_mutex_unlock(&out->lock);
3373 pthread_join(out->offload_thread, (void **) NULL);
3374 pthread_cond_destroy(&out->offload_cond);
3375
3376 return 0;
3377}
3378
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003379static int stop_output_stream(struct stream_out *out)
3380{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303381 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003382 struct audio_usecase *uc_info;
3383 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003384 bool has_voip_usecase =
3385 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003386
Eric Laurent994a6932013-07-17 11:51:42 -07003387 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003388 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389 uc_info = get_usecase_from_list(adev, out->usecase);
3390 if (uc_info == NULL) {
3391 ALOGE("%s: Could not find the usecase (%d) in the list",
3392 __func__, out->usecase);
3393 return -EINVAL;
3394 }
3395
Derek Chenea197282019-01-07 17:35:01 -08003396 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3397 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003398
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003399 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303400 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003401 if (adev->visualizer_stop_output != NULL)
3402 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003403
3404 audio_extn_dts_remove_state_notifier_node(out->usecase);
3405
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003406 if (adev->offload_effects_stop_output != NULL)
3407 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003408 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3409 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3410 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003411 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003412
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003413 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3414 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003415 voice_set_device_mute_flag(adev, false);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003416 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003417
Eric Laurent150dbfe2013-02-27 14:31:02 -08003418 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003419 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003420
3421 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003422 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003423
Aalique Grahame22e49102018-12-18 14:23:57 -08003424 audio_extn_extspk_update(adev->extspk);
3425
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003426 if (is_offload_usecase(out->usecase)) {
3427 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3428 adev->dsp_bit_width_enforce_mode,
3429 false);
3430 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003431 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3432 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3433 false);
3434
3435 if (ret != 0)
3436 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3437 /* default service interval was successfully updated,
3438 reopen USB backend with new service interval */
3439 ret = 0;
3440 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003441
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003442 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303443 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003444 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303445 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003446 ALOGV("Disable passthrough , reset mixer to pcm");
3447 /* NO_PASSTHROUGH */
3448 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003449 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003450 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3451 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003452
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303453 /* Must be called after removing the usecase from list */
3454 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303455 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303456
Manish Dewangan21a850a2017-08-14 12:03:55 +05303457 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003458 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3459 if (ret < 0)
3460 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3461 }
3462
juyuchen2d415992018-11-16 14:15:16 +08003463 /* 1) media + voip output routing to handset must route media back to
3464 speaker when voip stops.
3465 2) trigger voip input to reroute when voip output changes to
3466 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003467 if (has_voip_usecase ||
3468 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3469 struct listnode *node;
3470 struct audio_usecase *usecase;
3471 list_for_each(node, &adev->usecase_list) {
3472 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003473 if ((usecase->type == PCM_CAPTURE &&
3474 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3475 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003476 continue;
3477
3478 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3479 __func__, usecase->id, use_case_table[usecase->id],
3480 out->usecase, use_case_table[out->usecase]);
3481 select_devices(adev, usecase->id);
3482 }
3483 }
3484
Garmond Leung5fd0b552018-04-17 11:56:12 -07003485 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003486 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003487 return ret;
3488}
3489
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003490struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3491 unsigned int flags, unsigned int pcm_open_retry_count,
3492 struct pcm_config *config)
3493{
3494 struct pcm* pcm = NULL;
3495
3496 while (1) {
3497 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3498 if (pcm == NULL || !pcm_is_ready(pcm)) {
3499 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3500 if (pcm != NULL) {
3501 pcm_close(pcm);
3502 pcm = NULL;
3503 }
3504 if (pcm_open_retry_count-- == 0)
3505 return NULL;
3506
3507 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3508 continue;
3509 }
3510 break;
3511 }
3512
3513 if (pcm_is_ready(pcm)) {
3514 int ret = pcm_prepare(pcm);
3515 if (ret < 0) {
3516 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3517 pcm_close(pcm);
3518 pcm = NULL;
3519 }
3520 }
3521
3522 return pcm;
3523}
3524
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003525int start_output_stream(struct stream_out *out)
3526{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003527 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003528 struct audio_usecase *uc_info;
3529 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003530 char mixer_ctl_name[128];
3531 struct mixer_ctl *ctl = NULL;
3532 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303533 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003534 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003535
Haynes Mathew George380745d2017-10-04 15:27:45 -07003536 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003537 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3538 ret = -EINVAL;
3539 goto error_config;
3540 }
3541
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003542 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303543 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003544 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303545
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303546 if (CARD_STATUS_OFFLINE == out->card_status ||
3547 CARD_STATUS_OFFLINE == adev->card_status) {
3548 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303549 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303550 goto error_config;
3551 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303552
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003553 //Update incall music usecase to reflect correct voice session
3554 if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
3555 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
3556 if (ret != 0) {
3557 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
3558 __func__, ret);
3559 goto error_config;
3560 }
3561 }
3562
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303563 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003564 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003565 if (out->devices &
3566 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303567 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303568 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303569 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3570 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3571 ret = -EAGAIN;
3572 goto error_config;
3573 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303574 }
3575 }
3576 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303577 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3578 if (!adev->bt_sco_on) {
3579 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3580 //combo usecase just by pass a2dp
3581 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3582 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3583 } else {
3584 ALOGE("%s: SCO profile is not ready, return error", __func__);
3585 ret = -EAGAIN;
3586 goto error_config;
3587 }
3588 }
3589 }
3590
Eric Laurentb23d5282013-05-14 15:27:20 -07003591 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003592 if (out->pcm_device_id < 0) {
3593 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3594 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003595 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003596 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003597 }
3598
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003599 if (is_haptic_usecase) {
3600 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3601 if (adev->haptic_pcm_device_id < 0) {
3602 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3603 __func__, adev->haptic_pcm_device_id, out->usecase);
3604 ret = -EINVAL;
3605 goto error_config;
3606 }
3607 }
3608
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003610
3611 if (!uc_info) {
3612 ret = -ENOMEM;
3613 goto error_config;
3614 }
3615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 uc_info->id = out->usecase;
3617 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003618 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003619 uc_info->devices = out->devices;
3620 uc_info->in_snd_device = SND_DEVICE_NONE;
3621 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003622
3623 /* This must be called before adding this usecase to the list */
3624 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3625 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3626 /* USB backend is not reopened immediately.
3627 This is eventually done as part of select_devices */
3628 }
3629
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003630 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631
Wei Wangf7ca6c92017-11-21 14:51:20 -08003632 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303633 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3634 adev->perf_lock_opts,
3635 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303636
3637 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303638 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303639 if (audio_extn_passthru_is_enabled() &&
3640 audio_extn_passthru_is_passthrough_stream(out)) {
3641 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303642 }
3643 }
3644
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303645 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003646 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303647 if (!a2dp_combo) {
3648 check_a2dp_restore_l(adev, out, false);
3649 } else {
3650 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003651 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3652 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3653 else
3654 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303655 select_devices(adev, out->usecase);
3656 out->devices = dev;
3657 }
3658 } else {
3659 select_devices(adev, out->usecase);
3660 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003661
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003662 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
3663 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpurief53ce52018-09-11 18:00:09 -07003664 voice_set_device_mute_flag(adev, true);
Arun Mirpuri2ce92a62018-09-12 18:36:10 -07003665 }
Arun Mirpurief53ce52018-09-11 18:00:09 -07003666
Derek Chenea197282019-01-07 17:35:01 -08003667 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3668 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003669
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003670 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3671 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003672
3673 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003674 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003675 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3676 ALOGE("%s: pcm stream not ready", __func__);
3677 goto error_open;
3678 }
3679 ret = pcm_start(out->pcm);
3680 if (ret < 0) {
3681 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3682 goto error_open;
3683 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003684 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003685 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003686 unsigned int flags = PCM_OUT;
3687 unsigned int pcm_open_retry_count = 0;
3688 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3689 flags |= PCM_MMAP | PCM_NOIRQ;
3690 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003691 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003692 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003693 } else
3694 flags |= PCM_MONOTONIC;
3695
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003696 if ((adev->vr_audio_mode_enabled) &&
3697 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3698 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3699 "PCM_Dev %d Topology", out->pcm_device_id);
3700 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3701 if (!ctl) {
3702 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3703 __func__, mixer_ctl_name);
3704 } else {
3705 //if success use ULLPP
3706 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3707 __func__, mixer_ctl_name, out->pcm_device_id);
3708 //There is a still a possibility that some sessions
3709 // that request for FAST|RAW when 3D audio is active
3710 //can go through ULLPP. Ideally we expects apps to
3711 //listen to audio focus and stop concurrent playback
3712 //Also, we will look for mode flag (voice_in_communication)
3713 //before enabling the realtime flag.
3714 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3715 }
3716 }
3717
Surendar Karka91fa3682018-07-02 18:12:12 +05303718 if (out->realtime)
3719 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3720 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3721
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003722 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3723 flags, pcm_open_retry_count,
3724 &(out->config));
3725 if (out->pcm == NULL) {
3726 ret = -EIO;
3727 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003728 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003729
3730 if (is_haptic_usecase) {
3731 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3732 adev->haptic_pcm_device_id,
3733 flags, pcm_open_retry_count,
3734 &(adev->haptics_config));
3735 // failure to open haptics pcm shouldnt stop audio,
3736 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003737
3738 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3739 ALOGD("%s: enable haptic audio synchronization", __func__);
3740 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3741 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003742 }
3743
Surendar Karka91fa3682018-07-02 18:12:12 +05303744 if (!out->realtime)
3745 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303746 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003747
Zhou Song2b8f28f2017-09-11 10:51:38 +08003748 // apply volume for voip playback after path is set up
3749 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3750 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303751 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3752 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303753 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3754 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003755 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3756 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303757 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003758 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003759 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303760 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003761 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3762 adev->dsp_bit_width_enforce_mode,
3763 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003764 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003765 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003766 out->compr = compress_open(adev->snd_card,
3767 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003768 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003769 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303770 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303771 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3772 adev->card_status = CARD_STATUS_OFFLINE;
3773 out->card_status = CARD_STATUS_OFFLINE;
3774 ret = -EIO;
3775 goto error_open;
3776 }
3777
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003778 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003779 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003780 compress_close(out->compr);
3781 out->compr = NULL;
3782 ret = -EIO;
3783 goto error_open;
3784 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303785 /* compress_open sends params of the track, so reset the flag here */
3786 out->is_compr_metadata_avail = false;
3787
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003788 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003789 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003790
Fred Oh3f43e742015-03-04 18:42:34 -08003791 /* Since small bufs uses blocking writes, a write will be blocked
3792 for the default max poll time (20s) in the event of an SSR.
3793 Reduce the poll time to observe and deal with SSR faster.
3794 */
Ashish Jain5106d362016-05-11 19:23:33 +05303795 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003796 compress_set_max_poll_wait(out->compr, 1000);
3797 }
3798
Manish Dewangan69426c82017-01-30 17:35:36 +05303799 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303800 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303801
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003802 audio_extn_dts_create_state_notifier_node(out->usecase);
3803 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3804 popcount(out->channel_mask),
3805 out->playback_started);
3806
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003807#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303808 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003809 audio_extn_dolby_send_ddp_endp_params(adev);
3810#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303811 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3812 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003813 if (adev->visualizer_start_output != NULL)
3814 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3815 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303816 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003817 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003818 }
Derek Chenf13dd492018-11-13 14:53:51 -08003819
3820 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
3821 /* Update cached volume from media to offload/direct stream */
3822 struct listnode *node = NULL;
3823 list_for_each(node, &adev->active_outputs_list) {
3824 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3825 streams_output_ctxt_t,
3826 list);
3827 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3828 out->volume_l = out_ctxt->output->volume_l;
3829 out->volume_r = out_ctxt->output->volume_r;
3830 }
3831 }
3832 out_set_compr_volume(&out->stream,
3833 out->volume_l, out->volume_r);
3834 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003835 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003836
3837 if (ret == 0) {
3838 register_out_stream(out);
3839 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003840 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3841 ALOGE("%s: pcm stream not ready", __func__);
3842 goto error_open;
3843 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003844 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003845 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003846 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003847 if (ret < 0)
3848 goto error_open;
3849 }
3850 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003851 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303852 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003853 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003854
vivek mehtad15d2bf2019-05-17 13:35:10 -07003855 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3856 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3857 audio_low_latency_hint_start();
3858 }
3859
Manish Dewangan21a850a2017-08-14 12:03:55 +05303860 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003861 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003862 if (ret < 0)
3863 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3864 }
3865
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003866 // consider a scenario where on pause lower layers are tear down.
3867 // so on resume, swap mixer control need to be sent only when
3868 // backend is active, hence rather than sending from enable device
3869 // sending it from start of streamtream
3870
3871 platform_set_swap_channels(adev, true);
3872
Haynes Mathew George380745d2017-10-04 15:27:45 -07003873 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303874 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003875 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003876error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003877 if (adev->haptic_pcm) {
3878 pcm_close(adev->haptic_pcm);
3879 adev->haptic_pcm = NULL;
3880 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003881 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303882 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003883 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003884error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303885 /*
3886 * sleep 50ms to allow sufficient time for kernel
3887 * drivers to recover incases like SSR.
3888 */
3889 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003890 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303891 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003892 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003893}
3894
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003895static int check_input_parameters(uint32_t sample_rate,
3896 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003897 int channel_count,
3898 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003899{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003900 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003901
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303902 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3903 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3904 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003905 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003906 !audio_extn_compr_cap_format_supported(format) &&
3907 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003908 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003909
Aalique Grahame22e49102018-12-18 14:23:57 -08003910 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3911 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3912 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3913 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3914 return -EINVAL;
3915 }
3916
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003917 switch (channel_count) {
3918 case 1:
3919 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303920 case 3:
3921 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003922 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003923 case 8:
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05303924 case 10:
3925 case 12:
3926 case 14:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003927 break;
3928 default:
3929 ret = -EINVAL;
3930 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003931
3932 switch (sample_rate) {
3933 case 8000:
3934 case 11025:
3935 case 12000:
3936 case 16000:
3937 case 22050:
3938 case 24000:
3939 case 32000:
3940 case 44100:
3941 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003942 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303943 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003944 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303945 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 break;
3947 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003948 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003949 }
3950
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003951 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952}
3953
Naresh Tanniru04f71882018-06-26 17:46:22 +05303954
3955/** Add a value in a list if not already present.
3956 * @return true if value was successfully inserted or already present,
3957 * false if the list is full and does not contain the value.
3958 */
3959static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3960 for (size_t i = 0; i < list_length; i++) {
3961 if (list[i] == value) return true; // value is already present
3962 if (list[i] == 0) { // no values in this slot
3963 list[i] = value;
3964 return true; // value inserted
3965 }
3966 }
3967 return false; // could not insert value
3968}
3969
3970/** Add channel_mask in supported_channel_masks if not already present.
3971 * @return true if channel_mask was successfully inserted or already present,
3972 * false if supported_channel_masks is full and does not contain channel_mask.
3973 */
3974static void register_channel_mask(audio_channel_mask_t channel_mask,
3975 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3976 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3977 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3978}
3979
3980/** Add format in supported_formats if not already present.
3981 * @return true if format was successfully inserted or already present,
3982 * false if supported_formats is full and does not contain format.
3983 */
3984static void register_format(audio_format_t format,
3985 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3986 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3987 "%s: stream can not declare supporting its format %x", __func__, format);
3988}
3989/** Add sample_rate in supported_sample_rates if not already present.
3990 * @return true if sample_rate was successfully inserted or already present,
3991 * false if supported_sample_rates is full and does not contain sample_rate.
3992 */
3993static void register_sample_rate(uint32_t sample_rate,
3994 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3995 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3996 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3997}
3998
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003999static inline uint32_t lcm(uint32_t num1, uint32_t num2)
4000{
4001 uint32_t high = num1, low = num2, temp = 0;
4002
4003 if (!num1 || !num2)
4004 return 0;
4005
4006 if (num1 < num2) {
4007 high = num2;
4008 low = num1;
4009 }
4010
4011 while (low != 0) {
4012 temp = low;
4013 low = high % low;
4014 high = temp;
4015 }
4016 return (num1 * num2)/high;
4017}
4018
4019static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
4020{
4021 uint32_t remainder = 0;
4022
4023 if (!multiplier)
4024 return num;
4025
4026 remainder = num % multiplier;
4027 if (remainder)
4028 num += (multiplier - remainder);
4029
4030 return num;
4031}
4032
Aalique Grahame22e49102018-12-18 14:23:57 -08004033static size_t get_stream_buffer_size(size_t duration_ms,
4034 uint32_t sample_rate,
4035 audio_format_t format,
4036 int channel_count,
4037 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004038{
4039 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004040 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004041
Aalique Grahame22e49102018-12-18 14:23:57 -08004042 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004043 if (is_low_latency)
4044 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05304045
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004046 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08004047 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004048
Ralf Herzbd08d632018-09-28 15:50:49 +02004049 /* make sure the size is multiple of 32 bytes and additionally multiple of
4050 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004051 * At 48 kHz mono 16-bit PCM:
4052 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
4053 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004054 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07004055 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08004056 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07004057
4058 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004059}
4060
Aalique Grahame22e49102018-12-18 14:23:57 -08004061static size_t get_input_buffer_size(uint32_t sample_rate,
4062 audio_format_t format,
4063 int channel_count,
4064 bool is_low_latency)
4065{
4066 /* Don't know if USB HIFI in this context so use true to be conservative */
4067 if (check_input_parameters(sample_rate, format, channel_count,
4068 true /*is_usb_hifi */) != 0)
4069 return 0;
4070
4071 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
4072 sample_rate,
4073 format,
4074 channel_count,
4075 is_low_latency);
4076}
4077
Derek Chenf6318be2017-06-12 17:16:24 -04004078size_t get_output_period_size(uint32_t sample_rate,
4079 audio_format_t format,
4080 int channel_count,
4081 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05304082{
4083 size_t size = 0;
4084 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
4085
4086 if ((duration == 0) || (sample_rate == 0) ||
4087 (bytes_per_sample == 0) || (channel_count == 0)) {
4088 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
4089 bytes_per_sample, channel_count);
4090 return -EINVAL;
4091 }
4092
4093 size = (sample_rate *
4094 duration *
4095 bytes_per_sample *
4096 channel_count) / 1000;
4097 /*
4098 * To have same PCM samples for all channels, the buffer size requires to
4099 * be multiple of (number of channels * bytes per sample)
4100 * For writes to succeed, the buffer must be written at address which is multiple of 32
4101 */
4102 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4103
4104 return (size/(channel_count * bytes_per_sample));
4105}
4106
Zhou Song48453a02018-01-10 17:50:59 +08004107static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304108{
4109 uint64_t actual_frames_rendered = 0;
4110 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4111
4112 /* This adjustment accounts for buffering after app processor.
4113 * It is based on estimated DSP latency per use case, rather than exact.
4114 */
4115 int64_t platform_latency = platform_render_latency(out->usecase) *
4116 out->sample_rate / 1000000LL;
4117
Zhou Song48453a02018-01-10 17:50:59 +08004118 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304119 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4120 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4121 * hence only estimate.
4122 */
4123 int64_t signed_frames = out->written - kernel_buffer_size;
4124
4125 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
4126
Zhou Song48453a02018-01-10 17:50:59 +08004127 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304128 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004129 if (timestamp != NULL )
4130 *timestamp = out->writeAt;
4131 } else if (timestamp != NULL) {
4132 clock_gettime(CLOCK_MONOTONIC, timestamp);
4133 }
4134 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304135
4136 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
4137 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
4138 (long long int)out->written, (int)kernel_buffer_size,
4139 audio_bytes_per_sample(out->compr_config.codec->format),
4140 popcount(out->channel_mask));
4141
4142 return actual_frames_rendered;
4143}
4144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004145static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4146{
4147 struct stream_out *out = (struct stream_out *)stream;
4148
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004149 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004150}
4151
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004152static int out_set_sample_rate(struct audio_stream *stream __unused,
4153 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004154{
4155 return -ENOSYS;
4156}
4157
4158static size_t out_get_buffer_size(const struct audio_stream *stream)
4159{
4160 struct stream_out *out = (struct stream_out *)stream;
4161
Varun Balaraje49253e2017-07-06 19:48:56 +05304162 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304163 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304164 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304165 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4166 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4167 else
4168 return out->compr_config.fragment_size;
4169 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004170 return voice_extn_compress_voip_out_get_buffer_size(out);
Dhananjay Kumarac341582017-02-23 23:42:25 +05304171 else if (is_offload_usecase(out->usecase) &&
4172 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304173 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004174
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004175 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004176 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004177}
4178
4179static uint32_t out_get_channels(const struct audio_stream *stream)
4180{
4181 struct stream_out *out = (struct stream_out *)stream;
4182
4183 return out->channel_mask;
4184}
4185
4186static audio_format_t out_get_format(const struct audio_stream *stream)
4187{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004188 struct stream_out *out = (struct stream_out *)stream;
4189
4190 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004191}
4192
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004193static int out_set_format(struct audio_stream *stream __unused,
4194 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004195{
4196 return -ENOSYS;
4197}
4198
4199static int out_standby(struct audio_stream *stream)
4200{
4201 struct stream_out *out = (struct stream_out *)stream;
4202 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004203 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004204
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304205 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4206 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004208 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004209 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004210 if (adev->adm_deregister_stream)
4211 adev->adm_deregister_stream(adev->adm_data, out->handle);
4212
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004213 if (is_offload_usecase(out->usecase))
4214 stop_compressed_output_l(out);
4215
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004216 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004217 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004218 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4219 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304220 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004221 pthread_mutex_unlock(&adev->lock);
4222 pthread_mutex_unlock(&out->lock);
4223 ALOGD("VOIP output entered standby");
4224 return 0;
4225 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004226 if (out->pcm) {
4227 pcm_close(out->pcm);
4228 out->pcm = NULL;
4229 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004230 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4231 do_stop = out->playback_started;
4232 out->playback_started = false;
4233 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004234 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004235 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304236 out->send_next_track_params = false;
4237 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004238 out->gapless_mdata.encoder_delay = 0;
4239 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004240 if (out->compr != NULL) {
4241 compress_close(out->compr);
4242 out->compr = NULL;
4243 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004244 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004245 if (do_stop) {
4246 stop_output_stream(out);
4247 }
Lakshman Chaluvaraju40459022019-06-24 10:04:52 +05304248 // if fm is active route on selected device in UI
4249 audio_extn_fm_route_on_selected_device(adev, out->devices);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004250 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004251 }
4252 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304253 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004254 return 0;
4255}
4256
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304257static int out_on_error(struct audio_stream *stream)
4258{
4259 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004260 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304261
4262 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004263 // always send CMD_ERROR for offload streams, this
4264 // is needed e.g. when SSR happens within compress_open
4265 // since the stream is active, offload_callback_thread is also active.
4266 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4267 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004268 }
4269 pthread_mutex_unlock(&out->lock);
4270
4271 status = out_standby(&out->stream.common);
4272
4273 lock_output_stream(out);
4274 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004275 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304276 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304277
4278 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4279 ALOGD("Setting previous card status if offline");
4280 out->prev_card_status_offline = true;
4281 }
4282
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304283 pthread_mutex_unlock(&out->lock);
4284
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004285 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304286}
4287
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304288/*
4289 *standby implementation without locks, assumes that the callee already
4290 *has taken adev and out lock.
4291 */
4292int out_standby_l(struct audio_stream *stream)
4293{
4294 struct stream_out *out = (struct stream_out *)stream;
4295 struct audio_device *adev = out->dev;
4296
4297 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4298 stream, out->usecase, use_case_table[out->usecase]);
4299
4300 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004301 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304302 if (adev->adm_deregister_stream)
4303 adev->adm_deregister_stream(adev->adm_data, out->handle);
4304
4305 if (is_offload_usecase(out->usecase))
4306 stop_compressed_output_l(out);
4307
4308 out->standby = true;
4309 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4310 voice_extn_compress_voip_close_output_stream(stream);
4311 out->started = 0;
4312 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004313 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304314 return 0;
4315 } else if (!is_offload_usecase(out->usecase)) {
4316 if (out->pcm) {
4317 pcm_close(out->pcm);
4318 out->pcm = NULL;
4319 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004320 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4321 if (adev->haptic_pcm) {
4322 pcm_close(adev->haptic_pcm);
4323 adev->haptic_pcm = NULL;
4324 }
4325
4326 if (adev->haptic_buffer != NULL) {
4327 free(adev->haptic_buffer);
4328 adev->haptic_buffer = NULL;
4329 adev->haptic_buffer_size = 0;
4330 }
4331 adev->haptic_pcm_device_id = 0;
4332 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304333 } else {
4334 ALOGD("copl(%p):standby", out);
4335 out->send_next_track_params = false;
4336 out->is_compr_metadata_avail = false;
4337 out->gapless_mdata.encoder_delay = 0;
4338 out->gapless_mdata.encoder_padding = 0;
4339 if (out->compr != NULL) {
4340 compress_close(out->compr);
4341 out->compr = NULL;
4342 }
4343 }
4344 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004345 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304346 }
4347 ALOGD("%s: exit", __func__);
4348 return 0;
4349}
4350
Aalique Grahame22e49102018-12-18 14:23:57 -08004351static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004352{
Aalique Grahame22e49102018-12-18 14:23:57 -08004353 struct stream_out *out = (struct stream_out *)stream;
4354
4355 // We try to get the lock for consistency,
4356 // but it isn't necessary for these variables.
4357 // If we're not in standby, we may be blocked on a write.
4358 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4359 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4360 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4361
4362 if (locked) {
4363 pthread_mutex_unlock(&out->lock);
4364 }
4365
4366 // dump error info
4367 (void)error_log_dump(
4368 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4369
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004370 return 0;
4371}
4372
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004373static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4374{
4375 int ret = 0;
4376 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004377
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004378 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004379 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004380 return -EINVAL;
4381 }
4382
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304383 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004384
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004385 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4386 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304387 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004388 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004389 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4390 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304391 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004392 }
4393
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004394 ALOGV("%s new encoder delay %u and padding %u", __func__,
4395 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4396
4397 return 0;
4398}
4399
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004400static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4401{
4402 return out == adev->primary_output || out == adev->voice_tx_output;
4403}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004404
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304405// note: this call is safe only if the stream_cb is
4406// removed first in close_output_stream (as is done now).
4407static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4408{
4409 if (!stream || !parms)
4410 return;
4411
4412 struct stream_out *out = (struct stream_out *)stream;
4413 struct audio_device *adev = out->dev;
4414
4415 card_status_t status;
4416 int card;
4417 if (parse_snd_card_status(parms, &card, &status) < 0)
4418 return;
4419
4420 pthread_mutex_lock(&adev->lock);
4421 bool valid_cb = (card == adev->snd_card);
4422 pthread_mutex_unlock(&adev->lock);
4423
4424 if (!valid_cb)
4425 return;
4426
4427 lock_output_stream(out);
4428 if (out->card_status != status)
4429 out->card_status = status;
4430 pthread_mutex_unlock(&out->lock);
4431
4432 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4433 use_case_table[out->usecase],
4434 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4435
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304436 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304437 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304438 if (voice_is_call_state_active(adev) &&
4439 out == adev->primary_output) {
4440 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4441 pthread_mutex_lock(&adev->lock);
4442 voice_stop_call(adev);
4443 adev->mode = AUDIO_MODE_NORMAL;
4444 pthread_mutex_unlock(&adev->lock);
4445 }
4446 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304447 return;
4448}
4449
Kevin Rocardfce19002017-08-07 19:21:36 -07004450static int get_alive_usb_card(struct str_parms* parms) {
4451 int card;
4452 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4453 !audio_extn_usb_alive(card)) {
4454 return card;
4455 }
4456 return -ENODEV;
4457}
4458
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004459static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4460{
4461 struct stream_out *out = (struct stream_out *)stream;
4462 struct audio_device *adev = out->dev;
4463 struct str_parms *parms;
4464 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004465 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304466 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004467 bool reconfig = false;
4468 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004469
sangwoobc677242013-08-08 16:53:43 +09004470 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004471 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004472 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304473 if (!parms)
4474 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004475 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4476 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004477 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004478 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004479 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004480
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004481 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004482 * When HDMI cable is unplugged the music playback is paused and
4483 * the policy manager sends routing=0. But the audioflinger continues
4484 * to write data until standby time (3sec). As the HDMI core is
4485 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004486 * Avoid this by routing audio to speaker until standby.
4487 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004488 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4489 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304490 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004491 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4492 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004493 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304494 /*
4495 * When A2DP is disconnected the
4496 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004497 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304498 * (3sec). As BT is turned off, the write gets blocked.
4499 * Avoid this by routing audio to speaker until standby.
4500 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004501 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004502 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004503 !audio_extn_a2dp_source_is_ready() &&
4504 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304505 val = AUDIO_DEVICE_OUT_SPEAKER;
4506 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304507 /*
4508 * When USB headset is disconnected the music platback paused
4509 * and the policy manager send routing=0. But if the USB is connected
4510 * back before the standby time, AFE is not closed and opened
4511 * when USB is connected back. So routing to speker will guarantee
4512 * AFE reconfiguration and AFE will be opend once USB is connected again
4513 */
4514 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4515 (val == AUDIO_DEVICE_NONE) &&
4516 !audio_extn_usb_connected(parms)) {
4517 val = AUDIO_DEVICE_OUT_SPEAKER;
4518 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304519 /* To avoid a2dp to sco overlapping / BT device improper state
4520 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304521 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304522 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004523 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004524 if (val &
4525 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304526 //combo usecase just by pass a2dp
4527 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304528 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304529 } else {
4530 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4531 /* update device to a2dp and don't route as BT returned error
4532 * However it is still possible a2dp routing called because
4533 * of current active device disconnection (like wired headset)
4534 */
4535 out->devices = val;
4536 pthread_mutex_unlock(&out->lock);
4537 pthread_mutex_unlock(&adev->lock);
4538 goto error;
4539 }
4540 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304541 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004542
4543 audio_devices_t new_dev = val;
4544
4545 // Workaround: If routing to an non existing usb device, fail gracefully
4546 // The routing request will otherwise block during 10 second
4547 int card;
4548 if (audio_is_usb_out_device(new_dev) &&
4549 (card = get_alive_usb_card(parms)) >= 0) {
4550
4551 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4552 pthread_mutex_unlock(&adev->lock);
4553 pthread_mutex_unlock(&out->lock);
4554 ret = -ENOSYS;
4555 goto routing_fail;
4556 }
4557
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004558 /*
4559 * select_devices() call below switches all the usecases on the same
4560 * backend to the new device. Refer to check_usecases_codec_backend() in
4561 * the select_devices(). But how do we undo this?
4562 *
4563 * For example, music playback is active on headset (deep-buffer usecase)
4564 * and if we go to ringtones and select a ringtone, low-latency usecase
4565 * will be started on headset+speaker. As we can't enable headset+speaker
4566 * and headset devices at the same time, select_devices() switches the music
4567 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4568 * So when the ringtone playback is completed, how do we undo the same?
4569 *
4570 * We are relying on the out_set_parameters() call on deep-buffer output,
4571 * once the ringtone playback is ended.
4572 * NOTE: We should not check if the current devices are same as new devices.
4573 * Because select_devices() must be called to switch back the music
4574 * playback to headset.
4575 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004576 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004577 audio_devices_t new_dev = val;
4578 bool same_dev = out->devices == new_dev;
4579 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004580
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004581 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004582 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004583 if (adev->mode == AUDIO_MODE_IN_CALL) {
4584 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004585 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4586 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4587 audio_extn_usb_set_service_interval(true /*playback*/,
4588 service_interval,
4589 &reconfig);
4590 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4591 }
4592 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004593 }
4594 } else {
4595 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004596 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004597 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004598 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004599
4600 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004601 if (!same_dev) {
4602 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304603 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4604 adev->perf_lock_opts,
4605 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004606 if (adev->adm_on_routing_change)
4607 adev->adm_on_routing_change(adev->adm_data,
4608 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004609 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304610 if (!bypass_a2dp) {
4611 select_devices(adev, out->usecase);
4612 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004613 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4614 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4615 else
4616 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304617 select_devices(adev, out->usecase);
4618 out->devices = new_dev;
4619 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004620
4621 if (!same_dev) {
4622 // on device switch force swap, lower functions will make sure
4623 // to check if swap is allowed or not.
4624 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304625 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004626 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304627 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4628 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004629 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304630 pthread_mutex_lock(&out->compr_mute_lock);
4631 out->a2dp_compress_mute = false;
4632 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4633 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004634 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4635 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304636 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004637 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004638 }
4639
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004640 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004641 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004642
4643 /*handles device and call state changes*/
4644 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004645 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004646 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004647
4648 if (out == adev->primary_output) {
4649 pthread_mutex_lock(&adev->lock);
4650 audio_extn_set_parameters(adev, parms);
4651 pthread_mutex_unlock(&adev->lock);
4652 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004653 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004654 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004655 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004656
4657 audio_extn_dts_create_state_notifier_node(out->usecase);
4658 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4659 popcount(out->channel_mask),
4660 out->playback_started);
4661
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004662 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004663 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004664
Surendar Karkaf51b5842018-04-26 11:28:38 +05304665 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4666 sizeof(value));
4667 if (err >= 0) {
4668 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4669 audio_extn_send_dual_mono_mixing_coefficients(out);
4670 }
4671
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304672 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4673 if (err >= 0) {
4674 strlcpy(out->profile, value, sizeof(out->profile));
4675 ALOGV("updating stream profile with value '%s'", out->profile);
4676 lock_output_stream(out);
4677 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4678 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004679 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304680 out->sample_rate, out->bit_width,
4681 out->channel_mask, out->profile,
4682 &out->app_type_cfg);
4683 pthread_mutex_unlock(&out->lock);
4684 }
4685
Alexy Joseph98988832017-01-13 14:56:59 -08004686 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004687 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4688 // and vendor.audio.hal.output.suspend.supported is set to true
4689 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004690 //check suspend parameter only for low latency and if the property
4691 //is enabled
4692 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4693 ALOGI("%s: got suspend_playback %s", __func__, value);
4694 lock_output_stream(out);
4695 if (!strncmp(value, "false", 5)) {
4696 //suspend_playback=false is supposed to set QOS value back to 75%
4697 //the mixer control sent with value Enable will achieve that
4698 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4699 } else if (!strncmp (value, "true", 4)) {
4700 //suspend_playback=true is supposed to remove QOS value
4701 //resetting the mixer control will set the default value
4702 //for the mixer control which is Disable and this removes the QOS vote
4703 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4704 } else {
4705 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4706 " got %s", __func__, value);
4707 ret = -1;
4708 }
4709
4710 if (ret != 0) {
4711 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4712 __func__, out->pm_qos_mixer_path, ret);
4713 }
4714
4715 pthread_mutex_unlock(&out->lock);
4716 }
4717 }
4718 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004719 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304720error:
Eric Laurent994a6932013-07-17 11:51:42 -07004721 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004722 return ret;
4723}
4724
Paul McLeana50b7332018-12-17 08:24:21 -07004725static int in_set_microphone_direction(const struct audio_stream_in *stream,
4726 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004727 struct stream_in *in = (struct stream_in *)stream;
4728
4729 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4730
4731 in->direction = dir;
4732
4733 if (in->standby)
4734 return 0;
4735
4736 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004737}
4738
4739static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004740 struct stream_in *in = (struct stream_in *)stream;
4741
4742 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4743
4744 if (zoom > 1.0 || zoom < -1.0)
4745 return -EINVAL;
4746
4747 in->zoom = zoom;
4748
4749 if (in->standby)
4750 return 0;
4751
4752 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004753}
4754
4755
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004756static bool stream_get_parameter_channels(struct str_parms *query,
4757 struct str_parms *reply,
4758 audio_channel_mask_t *supported_channel_masks) {
4759 int ret = -1;
4760 char value[512];
4761 bool first = true;
4762 size_t i, j;
4763
4764 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4765 ret = 0;
4766 value[0] = '\0';
4767 i = 0;
4768 while (supported_channel_masks[i] != 0) {
4769 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4770 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4771 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304772 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004773
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304774 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004775 first = false;
4776 break;
4777 }
4778 }
4779 i++;
4780 }
4781 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4782 }
4783 return ret == 0;
4784}
4785
4786static bool stream_get_parameter_formats(struct str_parms *query,
4787 struct str_parms *reply,
4788 audio_format_t *supported_formats) {
4789 int ret = -1;
4790 char value[256];
4791 size_t i, j;
4792 bool first = true;
4793
4794 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4795 ret = 0;
4796 value[0] = '\0';
4797 i = 0;
4798 while (supported_formats[i] != 0) {
4799 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4800 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4801 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304802 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004803 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304804 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004805 first = false;
4806 break;
4807 }
4808 }
4809 i++;
4810 }
4811 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4812 }
4813 return ret == 0;
4814}
4815
4816static bool stream_get_parameter_rates(struct str_parms *query,
4817 struct str_parms *reply,
4818 uint32_t *supported_sample_rates) {
4819
4820 int i;
4821 char value[256];
4822 int ret = -1;
4823 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4824 ret = 0;
4825 value[0] = '\0';
4826 i=0;
4827 int cursor = 0;
4828 while (supported_sample_rates[i]) {
4829 int avail = sizeof(value) - cursor;
4830 ret = snprintf(value + cursor, avail, "%s%d",
4831 cursor > 0 ? "|" : "",
4832 supported_sample_rates[i]);
4833 if (ret < 0 || ret >= avail) {
4834 // if cursor is at the last element of the array
4835 // overwrite with \0 is duplicate work as
4836 // snprintf already put a \0 in place.
4837 // else
4838 // we had space to write the '|' at value[cursor]
4839 // (which will be overwritten) or no space to fill
4840 // the first element (=> cursor == 0)
4841 value[cursor] = '\0';
4842 break;
4843 }
4844 cursor += ret;
4845 ++i;
4846 }
4847 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4848 value);
4849 }
4850 return ret >= 0;
4851}
4852
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004853static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4854{
4855 struct stream_out *out = (struct stream_out *)stream;
4856 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004857 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004858 char value[256];
4859 struct str_parms *reply = str_parms_create();
4860 size_t i, j;
4861 int ret;
4862 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004863
4864 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004865 if (reply) {
4866 str_parms_destroy(reply);
4867 }
4868 if (query) {
4869 str_parms_destroy(query);
4870 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004871 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4872 return NULL;
4873 }
4874
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004875 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004876 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4877 if (ret >= 0) {
4878 value[0] = '\0';
4879 i = 0;
4880 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004881 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4882 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004883 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004884 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004885 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004886 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004887 first = false;
4888 break;
4889 }
4890 }
4891 i++;
4892 }
4893 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4894 str = str_parms_to_str(reply);
4895 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004896 voice_extn_out_get_parameters(out, query, reply);
4897 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004898 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004899
Alexy Joseph62142aa2015-11-16 15:10:34 -08004900
4901 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4902 if (ret >= 0) {
4903 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304904 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4905 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004906 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304907 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004908 } else {
4909 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304910 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004911 }
4912 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004913 if (str)
4914 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004915 str = str_parms_to_str(reply);
4916 }
4917
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004918 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4919 if (ret >= 0) {
4920 value[0] = '\0';
4921 i = 0;
4922 first = true;
4923 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004924 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4925 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004926 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004927 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004928 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004929 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004930 first = false;
4931 break;
4932 }
4933 }
4934 i++;
4935 }
4936 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004937 if (str)
4938 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004939 str = str_parms_to_str(reply);
4940 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004941
4942 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4943 if (ret >= 0) {
4944 value[0] = '\0';
4945 i = 0;
4946 first = true;
4947 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004948 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4949 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004950 if (!first) {
4951 strlcat(value, "|", sizeof(value));
4952 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004953 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004954 first = false;
4955 break;
4956 }
4957 }
4958 i++;
4959 }
4960 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4961 if (str)
4962 free(str);
4963 str = str_parms_to_str(reply);
4964 }
4965
Alexy Joseph98988832017-01-13 14:56:59 -08004966 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4967 //only low latency track supports suspend_resume
4968 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004969 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004970 if (str)
4971 free(str);
4972 str = str_parms_to_str(reply);
4973 }
4974
4975
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004976 str_parms_destroy(query);
4977 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004978 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004979 return str;
4980}
4981
4982static uint32_t out_get_latency(const struct audio_stream_out *stream)
4983{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004984 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004985 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004986 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004987
Alexy Josephaa54c872014-12-03 02:46:47 -08004988 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304989 lock_output_stream(out);
4990 latency = audio_extn_utils_compress_get_dsp_latency(out);
4991 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004992 } else if ((out->realtime) ||
4993 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004994 // since the buffer won't be filled up faster than realtime,
4995 // return a smaller number
4996 if (out->config.rate)
4997 period_ms = (out->af_period_multiplier * out->config.period_size *
4998 1000) / (out->config.rate);
4999 else
5000 period_ms = 0;
5001 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08005002 } else {
5003 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005004 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08005005 }
5006
yidongh0515e042017-07-06 15:00:34 +08005007 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08005008 latency += audio_extn_a2dp_get_encoder_latency();
5009
Anish Kumar50ebcbf2014-12-09 04:01:39 +05305010 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08005011 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005012}
5013
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305014static float AmpToDb(float amplification)
5015{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305016 float db = DSD_VOLUME_MIN_DB;
5017 if (amplification > 0) {
5018 db = 20 * log10(amplification);
5019 if(db < DSD_VOLUME_MIN_DB)
5020 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305021 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05305022 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305023}
5024
Arun Mirpuri5d170872019-03-26 13:21:31 -07005025static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
5026 float right)
5027{
5028 struct stream_out *out = (struct stream_out *)stream;
5029 long volume = 0;
5030 char mixer_ctl_name[128] = "";
5031 struct audio_device *adev = out->dev;
5032 struct mixer_ctl *ctl = NULL;
5033 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5034 PCM_PLAYBACK);
5035
5036 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5037 "Playback %d Volume", pcm_device_id);
5038 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5039 if (!ctl) {
5040 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5041 __func__, mixer_ctl_name);
5042 return -EINVAL;
5043 }
5044 if (left != right)
5045 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
5046 __func__, left, right);
5047 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
5048 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
5049 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
5050 __func__, mixer_ctl_name, volume);
5051 return -EINVAL;
5052 }
5053 return 0;
5054}
5055
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305056static int out_set_compr_volume(struct audio_stream_out *stream, float left,
5057 float right)
5058{
5059 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305060 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305061 char mixer_ctl_name[128];
5062 struct audio_device *adev = out->dev;
5063 struct mixer_ctl *ctl;
5064 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
5065 PCM_PLAYBACK);
5066
5067 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
5068 "Compress Playback %d Volume", pcm_device_id);
5069 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5070 if (!ctl) {
5071 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5072 __func__, mixer_ctl_name);
5073 return -EINVAL;
5074 }
5075 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
5076 __func__, mixer_ctl_name, left, right);
5077 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
5078 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
5079 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5080
5081 return 0;
5082}
5083
Zhou Song2b8f28f2017-09-11 10:51:38 +08005084static int out_set_voip_volume(struct audio_stream_out *stream, float left,
5085 float right)
5086{
5087 struct stream_out *out = (struct stream_out *)stream;
5088 char mixer_ctl_name[] = "App Type Gain";
5089 struct audio_device *adev = out->dev;
5090 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305091 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005092
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005093 if (!is_valid_volume(left, right)) {
5094 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5095 __func__, left, right);
5096 return -EINVAL;
5097 }
5098
Zhou Song2b8f28f2017-09-11 10:51:38 +08005099 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5100 if (!ctl) {
5101 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5102 __func__, mixer_ctl_name);
5103 return -EINVAL;
5104 }
5105
5106 set_values[0] = 0; //0: Rx Session 1:Tx Session
5107 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305108 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5109 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005110
5111 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5112 return 0;
5113}
5114
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305115static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5116 float right)
5117{
5118 struct stream_out *out = (struct stream_out *)stream;
5119 /* Volume control for pcm playback */
5120 if (left != right) {
5121 return -EINVAL;
5122 } else {
5123 char mixer_ctl_name[128];
5124 struct audio_device *adev = out->dev;
5125 struct mixer_ctl *ctl;
5126 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5127 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5128 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5129 if (!ctl) {
5130 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5131 return -EINVAL;
5132 }
5133
5134 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5135 int ret = mixer_ctl_set_value(ctl, 0, volume);
5136 if (ret < 0) {
5137 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5138 return -EINVAL;
5139 }
5140
5141 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5142
5143 return 0;
5144 }
5145}
5146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005147static int out_set_volume(struct audio_stream_out *stream, float left,
5148 float right)
5149{
Eric Laurenta9024de2013-04-04 09:19:12 -07005150 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005151 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305152 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005153
Arun Mirpuri5d170872019-03-26 13:21:31 -07005154 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005155 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5156 /* only take left channel into account: the API is for stereo anyway */
5157 out->muted = (left == 0.0f);
5158 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005159 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305160 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005161 /*
5162 * Set mute or umute on HDMI passthrough stream.
5163 * Only take left channel into account.
5164 * Mute is 0 and unmute 1
5165 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305166 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305167 } else if (out->format == AUDIO_FORMAT_DSD){
5168 char mixer_ctl_name[128] = "DSD Volume";
5169 struct audio_device *adev = out->dev;
5170 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5171
5172 if (!ctl) {
5173 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5174 __func__, mixer_ctl_name);
5175 return -EINVAL;
5176 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305177 volume[0] = (long)(AmpToDb(left));
5178 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305179 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5180 return 0;
Philippe Gravel1c9ac352019-05-28 16:08:37 -07005181 } else if ((out->devices & AUDIO_DEVICE_OUT_BUS) &&
5182 (audio_extn_auto_hal_get_snd_device_for_car_audio_stream(out) ==
5183 SND_DEVICE_OUT_BUS_MEDIA)) {
5184 ALOGD("%s: Overriding offload set volume for media bus stream", __func__);
5185 struct listnode *node = NULL;
5186 list_for_each(node, &adev->active_outputs_list) {
5187 streams_output_ctxt_t *out_ctxt = node_to_item(node,
5188 streams_output_ctxt_t,
5189 list);
5190 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
5191 out->volume_l = out_ctxt->output->volume_l;
5192 out->volume_r = out_ctxt->output->volume_r;
5193 }
5194 }
5195 if (!out->a2dp_compress_mute) {
5196 ret = out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
5197 }
5198 return ret;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005199 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305200 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005201 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305202 if (!out->a2dp_compress_mute)
5203 ret = out_set_compr_volume(stream, left, right);
5204 out->volume_l = left;
5205 out->volume_r = right;
5206 pthread_mutex_unlock(&out->compr_mute_lock);
5207 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005208 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005209 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005210 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5211 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5212 if (!out->standby) {
5213 audio_extn_utils_send_app_type_gain(out->dev,
5214 out->app_type_cfg.app_type,
5215 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005216 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005217 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005218 out->volume_l = left;
5219 out->volume_r = right;
5220 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005221 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5222 ALOGV("%s: MMAP set volume called", __func__);
5223 if (!out->standby)
5224 ret = out_set_mmap_volume(stream, left, right);
5225 out->volume_l = left;
5226 out->volume_r = right;
5227 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305228 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305229 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5230 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305231 /* Volume control for pcm playback */
5232 if (!out->standby)
5233 ret = out_set_pcm_volume(stream, left, right);
5234 else
5235 out->apply_volume = true;
5236
5237 out->volume_l = left;
5238 out->volume_r = right;
5239 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005240 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5241 ALOGV("%s: bus device set volume called", __func__);
5242 if (!out->standby)
5243 ret = out_set_pcm_volume(stream, left, right);
5244 out->volume_l = left;
5245 out->volume_r = right;
5246 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005247 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005249 return -ENOSYS;
5250}
5251
Zhou Songc9672822017-08-16 16:01:39 +08005252static void update_frames_written(struct stream_out *out, size_t bytes)
5253{
5254 size_t bpf = 0;
5255
5256 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5257 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5258 bpf = 1;
5259 else if (!is_offload_usecase(out->usecase))
5260 bpf = audio_bytes_per_sample(out->format) *
5261 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005262
5263 pthread_mutex_lock(&out->position_query_lock);
5264 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005265 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005266 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5267 }
5268 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005269}
5270
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005271int split_and_write_audio_haptic_data(struct stream_out *out,
5272 const void *buffer, size_t bytes_to_write)
5273{
5274 struct audio_device *adev = out->dev;
5275
5276 int ret = 0;
5277 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5278 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5279 size_t frame_size = channel_count * bytes_per_sample;
5280 size_t frame_count = bytes_to_write / frame_size;
5281
5282 bool force_haptic_path =
5283 property_get_bool("vendor.audio.test_haptic", false);
5284
5285 // extract Haptics data from Audio buffer
5286 bool alloc_haptic_buffer = false;
5287 int haptic_channel_count = adev->haptics_config.channels;
5288 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5289 size_t audio_frame_size = frame_size - haptic_frame_size;
5290 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5291
5292 if (adev->haptic_buffer == NULL) {
5293 alloc_haptic_buffer = true;
5294 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5295 free(adev->haptic_buffer);
5296 adev->haptic_buffer_size = 0;
5297 alloc_haptic_buffer = true;
5298 }
5299
5300 if (alloc_haptic_buffer) {
5301 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005302 if(adev->haptic_buffer == NULL) {
5303 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5304 return -ENOMEM;
5305 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005306 adev->haptic_buffer_size = total_haptic_buffer_size;
5307 }
5308
5309 size_t src_index = 0, aud_index = 0, hap_index = 0;
5310 uint8_t *audio_buffer = (uint8_t *)buffer;
5311 uint8_t *haptic_buffer = adev->haptic_buffer;
5312
5313 // This is required for testing only. This works for stereo data only.
5314 // One channel is fed to audio stream and other to haptic stream for testing.
5315 if (force_haptic_path)
5316 audio_frame_size = haptic_frame_size = bytes_per_sample;
5317
5318 for (size_t i = 0; i < frame_count; i++) {
5319 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5320 audio_frame_size);
5321 aud_index += audio_frame_size;
5322 src_index += audio_frame_size;
5323
5324 if (adev->haptic_pcm)
5325 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5326 haptic_frame_size);
5327 hap_index += haptic_frame_size;
5328 src_index += haptic_frame_size;
5329
5330 // This is required for testing only.
5331 // Discard haptic channel data.
5332 if (force_haptic_path)
5333 src_index += haptic_frame_size;
5334 }
5335
5336 // write to audio pipeline
5337 ret = pcm_write(out->pcm, (void *)audio_buffer,
5338 frame_count * audio_frame_size);
5339
5340 // write to haptics pipeline
5341 if (adev->haptic_pcm)
5342 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5343 frame_count * haptic_frame_size);
5344
5345 return ret;
5346}
5347
Aalique Grahame22e49102018-12-18 14:23:57 -08005348#ifdef NO_AUDIO_OUT
5349static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5350 const void *buffer __unused, size_t bytes)
5351{
5352 struct stream_out *out = (struct stream_out *)stream;
5353
5354 /* No Output device supported other than BT for playback.
5355 * Sleep for the amount of buffer duration
5356 */
5357 lock_output_stream(out);
5358 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5359 (const struct audio_stream_out *)&out->stream) /
5360 out_get_sample_rate(&out->stream.common));
5361 pthread_mutex_unlock(&out->lock);
5362 return bytes;
5363}
5364#endif
5365
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005366static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5367 size_t bytes)
5368{
5369 struct stream_out *out = (struct stream_out *)stream;
5370 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005371 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305372 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005373 const size_t frame_size = audio_stream_out_frame_size(stream);
5374 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305375 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005376
Haynes Mathew George380745d2017-10-04 15:27:45 -07005377 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005378 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305379
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305380 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005381
Dhananjay Kumarac341582017-02-23 23:42:25 +05305382 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305383 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305384 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5385 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005386 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305387 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305388 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305389 ALOGD(" %s: sound card is not active/SSR state", __func__);
5390 ret= -EIO;
5391 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305392 }
5393 }
5394
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305395 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305396 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305397 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305398 goto exit;
5399 }
5400
Haynes Mathew George16081042017-05-31 17:16:49 -07005401 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5402 ret = -EINVAL;
5403 goto exit;
5404 }
5405
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305406 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5407 !out->is_iec61937_info_available) {
5408
5409 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5410 out->is_iec61937_info_available = true;
5411 } else if (audio_extn_passthru_is_enabled()) {
5412 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305413 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305414
5415 if((out->format == AUDIO_FORMAT_DTS) ||
5416 (out->format == AUDIO_FORMAT_DTS_HD)) {
5417 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5418 buffer, bytes);
5419 if (ret) {
5420 if (ret != -ENOSYS) {
5421 out->is_iec61937_info_available = false;
5422 ALOGD("iec61937 transmission info not yet updated retry");
5423 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305424 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305425 /* if stream has started and after that there is
5426 * stream config change (iec transmission config)
5427 * then trigger select_device to update backend configuration.
5428 */
5429 out->stream_config_changed = true;
5430 pthread_mutex_lock(&adev->lock);
5431 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305432 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005433 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305434 ret = -EINVAL;
5435 goto exit;
5436 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305437 pthread_mutex_unlock(&adev->lock);
5438 out->stream_config_changed = false;
5439 out->is_iec61937_info_available = true;
5440 }
5441 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305442
Garmond Leung317cbf12017-09-13 16:20:50 -07005443 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305444 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5445 (out->is_iec61937_info_available == true)) {
5446 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5447 ret = -EINVAL;
5448 goto exit;
5449 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305450 }
5451 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305452
5453 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005454 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005455 if (!(out->devices &
5456 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305457 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305458 ret = -EIO;
5459 goto exit;
5460 }
5461 }
5462 }
5463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005464 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005465 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005466 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005467 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5468 ret = voice_extn_compress_voip_start_output_stream(out);
5469 else
5470 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005471 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005472 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005473 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005474 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005475 goto exit;
5476 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305477 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005478 if (last_known_cal_step != -1) {
5479 ALOGD("%s: retry previous failed cal level set", __func__);
5480 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305481 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005482 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305483
5484 if ((out->is_iec61937_info_available == true) &&
5485 (audio_extn_passthru_is_passthrough_stream(out))&&
5486 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5487 ret = -EINVAL;
5488 goto exit;
5489 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305490 if (out->set_dual_mono)
5491 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005493
Ashish Jain81eb2a82015-05-13 10:52:34 +05305494 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005495 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305496 adev->is_channel_status_set = true;
5497 }
5498
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305499 if ((adev->use_old_pspd_mix_ctrl == true) &&
5500 (out->pspd_coeff_sent == false)) {
5501 /*
5502 * Need to resend pspd coefficients after stream started for
5503 * older kernel version as it does not save the coefficients
5504 * and also stream has to be started for coeff to apply.
5505 */
5506 usecase = get_usecase_from_list(adev, out->usecase);
5507 if (usecase != NULL) {
Chaithanya Krishna Bacharajuc9f99712019-04-16 15:32:52 +05305508 audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305509 out->pspd_coeff_sent = true;
5510 }
5511 }
5512
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005513 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005514 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005515 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005516 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005517 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5518 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305519 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5520 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005521 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305522 out->send_next_track_params = false;
5523 out->is_compr_metadata_avail = false;
5524 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005525 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305526 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305527 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005528
Ashish Jain83a6cc22016-06-28 14:34:17 +05305529 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305530 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305531 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305532 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005533 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305534 return -EINVAL;
5535 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305536 audio_format_t dst_format = out->hal_op_format;
5537 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305538
Dieter Luecking5d57def2018-09-07 14:23:37 +02005539 /* prevent division-by-zero */
5540 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5541 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5542 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5543 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305544 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005545 ATRACE_END();
5546 return -EINVAL;
5547 }
5548
Ashish Jainf1eaa582016-05-23 20:54:24 +05305549 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5550 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5551
Ashish Jain83a6cc22016-06-28 14:34:17 +05305552 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305553 dst_format,
5554 buffer,
5555 src_format,
5556 frames);
5557
Ashish Jain83a6cc22016-06-28 14:34:17 +05305558 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305559 bytes_to_write);
5560
5561 /*Convert written bytes in audio flinger format*/
5562 if (ret > 0)
5563 ret = ((ret * format_to_bitwidth_table[out->format]) /
5564 format_to_bitwidth_table[dst_format]);
5565 }
5566 } else
5567 ret = compress_write(out->compr, buffer, bytes);
5568
Zhou Songc9672822017-08-16 16:01:39 +08005569 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5570 update_frames_written(out, bytes);
5571
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305572 if (ret < 0)
5573 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005574 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305575 /*msg to cb thread only if non blocking write is enabled*/
5576 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305577 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005578 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305579 } else if (-ENETRESET == ret) {
5580 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305581 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305582 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305583 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005584 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305585 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005586 }
Ashish Jain5106d362016-05-11 19:23:33 +05305587
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305588 /* Call compr start only when non-zero bytes of data is there to be rendered */
5589 if (!out->playback_started && ret > 0) {
5590 int status = compress_start(out->compr);
5591 if (status < 0) {
5592 ret = status;
5593 ALOGE("%s: compr start failed with err %d", __func__, errno);
5594 goto exit;
5595 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005596 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005597 out->playback_started = 1;
5598 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005599
5600 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5601 popcount(out->channel_mask),
5602 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005603 }
5604 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005605 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005606 return ret;
5607 } else {
5608 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005609 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005610 if (out->muted)
5611 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005612 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5613 __func__, frames, frame_size, bytes_to_write);
5614
Aalique Grahame22e49102018-12-18 14:23:57 -08005615 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005616 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5617 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5618 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005619 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5620 int16_t *src = (int16_t *)buffer;
5621 int16_t *dst = (int16_t *)buffer;
5622
5623 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5624 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005625 "out_write called for %s use case with wrong properties",
5626 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005627
5628 /*
5629 * FIXME: this can be removed once audio flinger mixer supports
5630 * mono output
5631 */
5632
5633 /*
5634 * Code below goes over each frame in the buffer and adds both
5635 * L and R samples and then divides by 2 to convert to mono
5636 */
5637 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5638 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5639 }
5640 bytes_to_write /= 2;
5641 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005642
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305643 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005644
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005645 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005646
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005647 if (out->config.rate)
5648 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5649 out->config.rate;
5650
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005651 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005652 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5653
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005654 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005655 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005656 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305657 out->convert_buffer != NULL) {
5658
5659 memcpy_by_audio_format(out->convert_buffer,
5660 out->hal_op_format,
5661 buffer,
5662 out->hal_ip_format,
5663 out->config.period_size * out->config.channels);
5664
5665 ret = pcm_write(out->pcm, out->convert_buffer,
5666 (out->config.period_size *
5667 out->config.channels *
5668 format_to_bitwidth_table[out->hal_op_format]));
5669 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305670 /*
5671 * To avoid underrun in DSP when the application is not pumping
5672 * data at required rate, check for the no. of bytes and ignore
5673 * pcm_write if it is less than actual buffer size.
5674 * It is a work around to a change in compress VOIP driver.
5675 */
5676 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5677 bytes < (out->config.period_size * out->config.channels *
5678 audio_bytes_per_sample(out->format))) {
5679 size_t voip_buf_size =
5680 out->config.period_size * out->config.channels *
5681 audio_bytes_per_sample(out->format);
5682 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5683 __func__, bytes, voip_buf_size);
5684 usleep(((uint64_t)voip_buf_size - bytes) *
5685 1000000 / audio_stream_out_frame_size(stream) /
5686 out_get_sample_rate(&out->stream.common));
5687 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005688 } else {
5689 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5690 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5691 else
5692 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5693 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305694 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005695
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005696 release_out_focus(out);
5697
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305698 if (ret < 0)
5699 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005700 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305701 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005702 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005703 }
5704
5705exit:
Zhou Songc9672822017-08-16 16:01:39 +08005706 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305707 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305708 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305709 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005710 pthread_mutex_unlock(&out->lock);
5711
5712 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005713 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005714 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305715 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305716 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305717 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305718 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305719 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305720 out->standby = true;
5721 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305722 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005723 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5724 /* prevent division-by-zero */
5725 uint32_t stream_size = audio_stream_out_frame_size(stream);
5726 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005727
Dieter Luecking5d57def2018-09-07 14:23:37 +02005728 if ((stream_size == 0) || (srate == 0)) {
5729 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5730 ATRACE_END();
5731 return -EINVAL;
5732 }
5733 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5734 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005735 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305736 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005737 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005738 return ret;
5739 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005740 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005741 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005742 return bytes;
5743}
5744
5745static int out_get_render_position(const struct audio_stream_out *stream,
5746 uint32_t *dsp_frames)
5747{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005748 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005749
5750 if (dsp_frames == NULL)
5751 return -EINVAL;
5752
5753 *dsp_frames = 0;
5754 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005755 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305756
5757 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5758 * this operation and adev_close_output_stream(where out gets reset).
5759 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305760 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005761 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305762 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005763 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305764 return 0;
5765 }
5766
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005767 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305768 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305769 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005770 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305771 if (ret < 0)
5772 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005773 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305774 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005775 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305776 if (-ENETRESET == ret) {
5777 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305778 out->card_status = CARD_STATUS_OFFLINE;
5779 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305780 } else if(ret < 0) {
5781 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305782 ret = -EINVAL;
5783 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305784 /*
5785 * Handle corner case where compress session is closed during SSR
5786 * and timestamp is queried
5787 */
5788 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305789 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305790 } else if (out->prev_card_status_offline) {
5791 ALOGE("ERROR: previously sound card was offline,return error");
5792 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305793 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305794 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005795 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305796 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305797 pthread_mutex_unlock(&out->lock);
5798 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005799 } else if (audio_is_linear_pcm(out->format)) {
5800 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005801 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005802 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005803 } else
5804 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005805}
5806
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005807static int out_add_audio_effect(const struct audio_stream *stream __unused,
5808 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005809{
5810 return 0;
5811}
5812
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005813static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5814 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005815{
5816 return 0;
5817}
5818
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005819static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5820 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005821{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305822 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005823}
5824
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005825static int out_get_presentation_position(const struct audio_stream_out *stream,
5826 uint64_t *frames, struct timespec *timestamp)
5827{
5828 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305829 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005830 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005831
Ashish Jain5106d362016-05-11 19:23:33 +05305832 /* below piece of code is not guarded against any lock because audioFliner serializes
5833 * this operation and adev_close_output_stream( where out gets reset).
5834 */
5835 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305836 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005837 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305838 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5839 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5840 return 0;
5841 }
5842
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005843 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005844
Ashish Jain5106d362016-05-11 19:23:33 +05305845 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5846 ret = compress_get_tstamp(out->compr, &dsp_frames,
5847 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005848 // Adjustment accounts for A2dp encoder latency with offload usecases
5849 // Note: Encoder latency is returned in ms.
5850 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5851 unsigned long offset =
5852 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5853 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5854 }
Ashish Jain5106d362016-05-11 19:23:33 +05305855 ALOGVV("%s rendered frames %ld sample_rate %d",
5856 __func__, dsp_frames, out->sample_rate);
5857 *frames = dsp_frames;
5858 if (ret < 0)
5859 ret = -errno;
5860 if (-ENETRESET == ret) {
5861 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305862 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305863 ret = -EINVAL;
5864 } else
5865 ret = 0;
5866 /* this is the best we can do */
5867 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005868 } else {
5869 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005870 unsigned int avail;
5871 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5872 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5873 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5874 // This adjustment accounts for buffering after app processor.
5875 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005876 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005877 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005878
Weiyin Jiangd4633762018-03-16 12:05:03 +08005879 // Adjustment accounts for A2dp encoder latency with non offload usecases
5880 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5881 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5882 signed_frames -=
5883 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5884 }
5885
5886 // It would be unusual for this value to be negative, but check just in case ...
5887 if (signed_frames >= 0) {
5888 *frames = signed_frames;
5889 ret = 0;
5890 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005891 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305892 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305893 *frames = out->written;
5894 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305895 if (is_offload_usecase(out->usecase))
5896 ret = -EINVAL;
5897 else
5898 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005899 }
5900 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005901 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005902 return ret;
5903}
5904
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005905static int out_set_callback(struct audio_stream_out *stream,
5906 stream_callback_t callback, void *cookie)
5907{
5908 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005909 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005910
5911 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005912 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005913 out->client_callback = callback;
5914 out->client_cookie = cookie;
5915 if (out->adsp_hdlr_stream_handle) {
5916 ret = audio_extn_adsp_hdlr_stream_set_callback(
5917 out->adsp_hdlr_stream_handle,
5918 callback,
5919 cookie);
5920 if (ret)
5921 ALOGW("%s:adsp hdlr callback registration failed %d",
5922 __func__, ret);
5923 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005924 pthread_mutex_unlock(&out->lock);
5925 return 0;
5926}
5927
5928static int out_pause(struct audio_stream_out* stream)
5929{
5930 struct stream_out *out = (struct stream_out *)stream;
5931 int status = -ENOSYS;
5932 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005933 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005934 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005935 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005936 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305937 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305938 status = compress_pause(out->compr);
5939
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005940 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005941
Mingming Yin21854652016-04-13 11:54:02 -07005942 if (audio_extn_passthru_is_active()) {
5943 ALOGV("offload use case, pause passthru");
5944 audio_extn_passthru_on_pause(out);
5945 }
5946
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305947 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005948 audio_extn_dts_notify_playback_state(out->usecase, 0,
5949 out->sample_rate, popcount(out->channel_mask),
5950 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005951 }
5952 pthread_mutex_unlock(&out->lock);
5953 }
5954 return status;
5955}
5956
5957static int out_resume(struct audio_stream_out* stream)
5958{
5959 struct stream_out *out = (struct stream_out *)stream;
5960 int status = -ENOSYS;
5961 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005962 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005963 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005964 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005965 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005966 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305967 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305968 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005969 }
5970 if (!status) {
5971 out->offload_state = OFFLOAD_STATE_PLAYING;
5972 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305973 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005974 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5975 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005976 }
5977 pthread_mutex_unlock(&out->lock);
5978 }
5979 return status;
5980}
5981
5982static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5983{
5984 struct stream_out *out = (struct stream_out *)stream;
5985 int status = -ENOSYS;
5986 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005987 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005988 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005989 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5990 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5991 else
5992 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5993 pthread_mutex_unlock(&out->lock);
5994 }
5995 return status;
5996}
5997
5998static int out_flush(struct audio_stream_out* stream)
5999{
6000 struct stream_out *out = (struct stream_out *)stream;
6001 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07006002 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006003 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006004 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006005 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
6006 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07006007 } else {
6008 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
6009 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08006010 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006011 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07006012 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006013 return 0;
6014 }
6015 return -ENOSYS;
6016}
6017
Haynes Mathew George16081042017-05-31 17:16:49 -07006018static int out_stop(const struct audio_stream_out* stream)
6019{
6020 struct stream_out *out = (struct stream_out *)stream;
6021 struct audio_device *adev = out->dev;
6022 int ret = -ENOSYS;
6023
6024 ALOGV("%s", __func__);
6025 pthread_mutex_lock(&adev->lock);
6026 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6027 out->playback_started && out->pcm != NULL) {
6028 pcm_stop(out->pcm);
6029 ret = stop_output_stream(out);
6030 out->playback_started = false;
6031 }
6032 pthread_mutex_unlock(&adev->lock);
6033 return ret;
6034}
6035
6036static int out_start(const struct audio_stream_out* stream)
6037{
6038 struct stream_out *out = (struct stream_out *)stream;
6039 struct audio_device *adev = out->dev;
6040 int ret = -ENOSYS;
6041
6042 ALOGV("%s", __func__);
6043 pthread_mutex_lock(&adev->lock);
6044 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
6045 !out->playback_started && out->pcm != NULL) {
6046 ret = start_output_stream(out);
6047 if (ret == 0) {
6048 out->playback_started = true;
6049 }
6050 }
6051 pthread_mutex_unlock(&adev->lock);
6052 return ret;
6053}
6054
6055/*
6056 * Modify config->period_count based on min_size_frames
6057 */
6058static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
6059{
6060 int periodCountRequested = (min_size_frames + config->period_size - 1)
6061 / config->period_size;
6062 int periodCount = MMAP_PERIOD_COUNT_MIN;
6063
6064 ALOGV("%s original config.period_size = %d config.period_count = %d",
6065 __func__, config->period_size, config->period_count);
6066
6067 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
6068 periodCount *= 2;
6069 }
6070 config->period_count = periodCount;
6071
6072 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
6073}
6074
Phil Burkfe17efd2019-03-25 10:23:35 -07006075// Read offset for the positional timestamp from a persistent vendor property.
6076// This is to workaround apparent inaccuracies in the timing information that
6077// is used by the AAudio timing model. The inaccuracies can cause glitches.
6078static int64_t get_mmap_out_time_offset() {
6079 const int32_t kDefaultOffsetMicros = 0;
6080 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006081 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07006082 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
6083 return mmap_time_offset_micros * (int64_t)1000;
6084}
6085
Haynes Mathew George16081042017-05-31 17:16:49 -07006086static int out_create_mmap_buffer(const struct audio_stream_out *stream,
6087 int32_t min_size_frames,
6088 struct audio_mmap_buffer_info *info)
6089{
6090 struct stream_out *out = (struct stream_out *)stream;
6091 struct audio_device *adev = out->dev;
6092 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07006093 unsigned int offset1 = 0;
6094 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006095 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006096 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07006097 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07006098
Arun Mirpuri5d170872019-03-26 13:21:31 -07006099 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306100 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07006101 pthread_mutex_lock(&adev->lock);
6102
Sharad Sanglec6f32552018-05-04 16:15:38 +05306103 if (CARD_STATUS_OFFLINE == out->card_status ||
6104 CARD_STATUS_OFFLINE == adev->card_status) {
6105 ALOGW("out->card_status or adev->card_status offline, try again");
6106 ret = -EIO;
6107 goto exit;
6108 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006109 if (info == NULL || min_size_frames == 0) {
6110 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6111 ret = -EINVAL;
6112 goto exit;
6113 }
6114 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6115 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6116 ret = -ENOSYS;
6117 goto exit;
6118 }
6119 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6120 if (out->pcm_device_id < 0) {
6121 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6122 __func__, out->pcm_device_id, out->usecase);
6123 ret = -EINVAL;
6124 goto exit;
6125 }
6126
6127 adjust_mmap_period_count(&out->config, min_size_frames);
6128
Arun Mirpuri5d170872019-03-26 13:21:31 -07006129 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006130 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6131 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6132 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306133 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306134 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6135 out->card_status = CARD_STATUS_OFFLINE;
6136 adev->card_status = CARD_STATUS_OFFLINE;
6137 ret = -EIO;
6138 goto exit;
6139 }
6140
Haynes Mathew George16081042017-05-31 17:16:49 -07006141 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6142 step = "open";
6143 ret = -ENODEV;
6144 goto exit;
6145 }
6146 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6147 if (ret < 0) {
6148 step = "begin";
6149 goto exit;
6150 }
6151 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006152 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006153 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006154 ret = platform_get_mmap_data_fd(adev->platform,
6155 out->pcm_device_id, 0 /*playback*/,
6156 &info->shared_memory_fd,
6157 &mmap_size);
6158 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006159 // Fall back to non exclusive mode
6160 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6161 } else {
6162 if (mmap_size < buffer_size) {
6163 step = "mmap";
6164 goto exit;
6165 }
6166 // FIXME: indicate exclusive mode support by returning a negative buffer size
6167 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006168 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006169 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006170 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006171
6172 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6173 if (ret < 0) {
6174 step = "commit";
6175 goto exit;
6176 }
6177
Phil Burkfe17efd2019-03-25 10:23:35 -07006178 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6179
Haynes Mathew George16081042017-05-31 17:16:49 -07006180 out->standby = false;
6181 ret = 0;
6182
Arun Mirpuri5d170872019-03-26 13:21:31 -07006183 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006184 __func__, info->shared_memory_address, info->buffer_size_frames);
6185
6186exit:
6187 if (ret != 0) {
6188 if (out->pcm == NULL) {
6189 ALOGE("%s: %s - %d", __func__, step, ret);
6190 } else {
6191 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6192 pcm_close(out->pcm);
6193 out->pcm = NULL;
6194 }
6195 }
6196 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306197 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006198 return ret;
6199}
6200
6201static int out_get_mmap_position(const struct audio_stream_out *stream,
6202 struct audio_mmap_position *position)
6203{
6204 struct stream_out *out = (struct stream_out *)stream;
6205 ALOGVV("%s", __func__);
6206 if (position == NULL) {
6207 return -EINVAL;
6208 }
6209 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006210 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006211 return -ENOSYS;
6212 }
6213 if (out->pcm == NULL) {
6214 return -ENOSYS;
6215 }
6216
6217 struct timespec ts = { 0, 0 };
6218 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6219 if (ret < 0) {
6220 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6221 return ret;
6222 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006223 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6224 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006225 return 0;
6226}
6227
6228
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006229/** audio_stream_in implementation **/
6230static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6231{
6232 struct stream_in *in = (struct stream_in *)stream;
6233
6234 return in->config.rate;
6235}
6236
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006237static int in_set_sample_rate(struct audio_stream *stream __unused,
6238 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006239{
6240 return -ENOSYS;
6241}
6242
6243static size_t in_get_buffer_size(const struct audio_stream *stream)
6244{
6245 struct stream_in *in = (struct stream_in *)stream;
6246
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006247 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6248 return voice_extn_compress_voip_in_get_buffer_size(in);
Mingming Yine62d7842013-10-25 16:26:03 -07006249 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6250 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306251 else if(audio_extn_cin_attached_usecase(in->usecase))
6252 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006253
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006254 return in->config.period_size * in->af_period_multiplier *
6255 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006256}
6257
6258static uint32_t in_get_channels(const struct audio_stream *stream)
6259{
6260 struct stream_in *in = (struct stream_in *)stream;
6261
6262 return in->channel_mask;
6263}
6264
6265static audio_format_t in_get_format(const struct audio_stream *stream)
6266{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006267 struct stream_in *in = (struct stream_in *)stream;
6268
6269 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006270}
6271
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006272static int in_set_format(struct audio_stream *stream __unused,
6273 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006274{
6275 return -ENOSYS;
6276}
6277
6278static int in_standby(struct audio_stream *stream)
6279{
6280 struct stream_in *in = (struct stream_in *)stream;
6281 struct audio_device *adev = in->dev;
6282 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306283 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6284 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006285 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306286
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006287 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006288 if (!in->standby && in->is_st_session) {
6289 ALOGD("%s: sound trigger pcm stop lab", __func__);
6290 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006291 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006292 in->standby = 1;
6293 }
6294
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006295 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006296 if (adev->adm_deregister_stream)
6297 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6298
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006299 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006300 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006301 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006302 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006303 voice_extn_compress_voip_close_input_stream(stream);
6304 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006305 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6306 do_stop = in->capture_started;
6307 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006308 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306309 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05306310 audio_extn_cin_close_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006311 }
6312
Arun Mirpuri5d170872019-03-26 13:21:31 -07006313 if (in->pcm) {
6314 ATRACE_BEGIN("pcm_in_close");
6315 pcm_close(in->pcm);
6316 ATRACE_END();
6317 in->pcm = NULL;
6318 }
6319
Carter Hsu2e429db2019-05-14 18:50:52 +08006320 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Aalique Grahame22e49102018-12-18 14:23:57 -08006321 adev->enable_voicerx = false;
Carter Hsu2e429db2019-05-14 18:50:52 +08006322
6323 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006324 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006325
6326 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6327 adev->num_va_sessions--;
6328
Eric Laurent150dbfe2013-02-27 14:31:02 -08006329 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006330 }
6331 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006332 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006333 return status;
6334}
6335
Aalique Grahame22e49102018-12-18 14:23:57 -08006336static int in_dump(const struct audio_stream *stream,
6337 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006338{
Aalique Grahame22e49102018-12-18 14:23:57 -08006339 struct stream_in *in = (struct stream_in *)stream;
6340
6341 // We try to get the lock for consistency,
6342 // but it isn't necessary for these variables.
6343 // If we're not in standby, we may be blocked on a read.
6344 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6345 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6346 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6347 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6348
6349 if (locked) {
6350 pthread_mutex_unlock(&in->lock);
6351 }
6352
6353 // dump error info
6354 (void)error_log_dump(
6355 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6356
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006357 return 0;
6358}
6359
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306360static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6361{
6362 if (!stream || !parms)
6363 return;
6364
6365 struct stream_in *in = (struct stream_in *)stream;
6366 struct audio_device *adev = in->dev;
6367
6368 card_status_t status;
6369 int card;
6370 if (parse_snd_card_status(parms, &card, &status) < 0)
6371 return;
6372
6373 pthread_mutex_lock(&adev->lock);
6374 bool valid_cb = (card == adev->snd_card);
6375 pthread_mutex_unlock(&adev->lock);
6376
6377 if (!valid_cb)
6378 return;
6379
6380 lock_input_stream(in);
6381 if (in->card_status != status)
6382 in->card_status = status;
6383 pthread_mutex_unlock(&in->lock);
6384
6385 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6386 use_case_table[in->usecase],
6387 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6388
6389 // a better solution would be to report error back to AF and let
6390 // it put the stream to standby
6391 if (status == CARD_STATUS_OFFLINE)
6392 in_standby(&in->stream.common);
6393
6394 return;
6395}
6396
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006397static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6398{
6399 struct stream_in *in = (struct stream_in *)stream;
6400 struct audio_device *adev = in->dev;
6401 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006402 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006403 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006404
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306405 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006406 parms = str_parms_create_str(kvpairs);
6407
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306408 if (!parms)
6409 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006410 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006411 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006412
6413 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6414 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006415 val = atoi(value);
6416 /* no audio source uses val == 0 */
6417 if ((in->source != val) && (val != 0)) {
6418 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006419 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6420 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6421 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006422 (in->config.rate == 8000 || in->config.rate == 16000 ||
6423 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006424 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006425 err = voice_extn_compress_voip_open_input_stream(in);
6426 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006427 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006428 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006429 }
6430 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006431 }
6432 }
6433
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006434 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6435 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006436 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006437 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6438
6439 // Workaround: If routing to an non existing usb device, fail gracefully
6440 // The routing request will otherwise block during 10 second
6441 int card;
6442 if (audio_is_usb_in_device(val) &&
6443 (card = get_alive_usb_card(parms)) >= 0) {
6444
6445 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6446 ret = -ENOSYS;
6447 } else {
6448
6449 in->device = val;
6450 /* If recording is in progress, change the tx device to new device */
6451 if (!in->standby && !in->is_st_session) {
6452 ALOGV("update input routing change");
6453 // inform adm before actual routing to prevent glitches.
6454 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006455 adev->adm_on_routing_change(adev->adm_data,
6456 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006457 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006458 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6459 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006460 }
6461 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006462 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006463 }
6464 }
6465
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306466 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6467 if (err >= 0) {
6468 strlcpy(in->profile, value, sizeof(in->profile));
6469 ALOGV("updating stream profile with value '%s'", in->profile);
6470 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6471 &adev->streams_input_cfg_list,
6472 in->device, in->flags, in->format,
6473 in->sample_rate, in->bit_width,
6474 in->profile, &in->app_type_cfg);
6475 }
6476
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006477 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006478 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006479
6480 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306481error:
Eric Laurent994a6932013-07-17 11:51:42 -07006482 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006483 return ret;
6484}
6485
6486static char* in_get_parameters(const struct audio_stream *stream,
6487 const char *keys)
6488{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006489 struct stream_in *in = (struct stream_in *)stream;
6490 struct str_parms *query = str_parms_create_str(keys);
6491 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006492 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006493
6494 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006495 if (reply) {
6496 str_parms_destroy(reply);
6497 }
6498 if (query) {
6499 str_parms_destroy(query);
6500 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006501 ALOGE("in_get_parameters: failed to create query or reply");
6502 return NULL;
6503 }
6504
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006505 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006506
6507 voice_extn_in_get_parameters(in, query, reply);
6508
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006509 stream_get_parameter_channels(query, reply,
6510 &in->supported_channel_masks[0]);
6511 stream_get_parameter_formats(query, reply,
6512 &in->supported_formats[0]);
6513 stream_get_parameter_rates(query, reply,
6514 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006515 str = str_parms_to_str(reply);
6516 str_parms_destroy(query);
6517 str_parms_destroy(reply);
6518
6519 ALOGV("%s: exit: returns - %s", __func__, str);
6520 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006521}
6522
Aalique Grahame22e49102018-12-18 14:23:57 -08006523static int in_set_gain(struct audio_stream_in *stream,
6524 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006525{
Aalique Grahame22e49102018-12-18 14:23:57 -08006526 struct stream_in *in = (struct stream_in *)stream;
6527 char mixer_ctl_name[128];
6528 struct mixer_ctl *ctl;
6529 int ctl_value;
6530
6531 ALOGV("%s: gain %f", __func__, gain);
6532
6533 if (stream == NULL)
6534 return -EINVAL;
6535
6536 /* in_set_gain() only used to silence MMAP capture for now */
6537 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6538 return -ENOSYS;
6539
6540 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6541
6542 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6543 if (!ctl) {
6544 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6545 __func__, mixer_ctl_name);
6546 return -ENOSYS;
6547 }
6548
6549 if (gain < RECORD_GAIN_MIN)
6550 gain = RECORD_GAIN_MIN;
6551 else if (gain > RECORD_GAIN_MAX)
6552 gain = RECORD_GAIN_MAX;
6553 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6554
6555 mixer_ctl_set_value(ctl, 0, ctl_value);
6556
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006557 return 0;
6558}
6559
6560static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6561 size_t bytes)
6562{
6563 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306564
6565 if (in == NULL) {
6566 ALOGE("%s: stream_in ptr is NULL", __func__);
6567 return -EINVAL;
6568 }
6569
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006570 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306571 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306572 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006573
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006574 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306575
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006576 if (in->is_st_session) {
6577 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6578 /* Read from sound trigger HAL */
6579 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006580 if (in->standby) {
6581 adev->num_va_sessions++;
6582 in->standby = 0;
6583 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006584 pthread_mutex_unlock(&in->lock);
6585 return bytes;
6586 }
6587
Haynes Mathew George16081042017-05-31 17:16:49 -07006588 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6589 ret = -ENOSYS;
6590 goto exit;
6591 }
6592
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006593 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6594 !in->standby && adev->adm_routing_changed) {
6595 ret = -ENOSYS;
6596 goto exit;
6597 }
6598
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006599 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006600 pthread_mutex_lock(&adev->lock);
6601 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6602 ret = voice_extn_compress_voip_start_input_stream(in);
6603 else
6604 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006605 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6606 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006607 pthread_mutex_unlock(&adev->lock);
6608 if (ret != 0) {
6609 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006610 }
6611 in->standby = 0;
6612 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006613
Deeraj Soman30cc7ae2019-03-18 16:26:55 +05306614 /* Avoid read if capture_stopped is set */
6615 if (android_atomic_acquire_load(&(in->capture_stopped)) > 0) {
6616 ALOGD("%s: force stopped catpure session, ignoring read request", __func__);
6617 ret = -EINVAL;
6618 goto exit;
6619 }
6620
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006621 // what's the duration requested by the client?
6622 long ns = 0;
6623
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306624 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006625 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6626 in->config.rate;
6627
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006628 ret = request_in_focus(in, ns);
6629 if (ret != 0)
6630 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006631 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006632
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306633 if (audio_extn_cin_attached_usecase(in->usecase)) {
6634 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6635 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306636 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006637 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306638 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006639 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006640 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006641 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006642 } else if (audio_extn_ffv_get_stream() == in) {
6643 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306644 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006645 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306646 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6647 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6648 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6649 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306650 ret = -EINVAL;
6651 goto exit;
6652 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306653 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306654 ret = -errno;
6655 }
6656 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306657 /* bytes read is always set to bytes for non compress usecases */
6658 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006659 }
6660
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006661 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006662
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006663 /*
Quinn Malef6050362019-01-30 15:55:40 -08006664 * Instead of writing zeroes here, we could trust the hardware to always
6665 * provide zeroes when muted. This is also muted with voice recognition
6666 * usecases so that other clients do not have access to voice recognition
6667 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006668 */
Quinn Malef6050362019-01-30 15:55:40 -08006669 if ((ret == 0 && voice_get_mic_mute(adev) &&
6670 !voice_is_in_call_rec_stream(in) &&
6671 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6672 (adev->num_va_sessions &&
6673 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6674 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6675 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006676 memset(buffer, 0, bytes);
6677
6678exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306679 frame_size = audio_stream_in_frame_size(stream);
6680 if (frame_size > 0)
6681 in->frames_read += bytes_read/frame_size;
6682
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006683 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306684 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006685 pthread_mutex_unlock(&in->lock);
6686
6687 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306688 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306689 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306690 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306691 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306692 in->standby = true;
6693 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306694 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6695 bytes_read = bytes;
6696 memset(buffer, 0, bytes);
6697 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006698 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006699 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6700 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006701 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306702 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306703 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006704 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306705 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006706}
6707
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006708static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006709{
6710 return 0;
6711}
6712
Aalique Grahame22e49102018-12-18 14:23:57 -08006713static int in_get_capture_position(const struct audio_stream_in *stream,
6714 int64_t *frames, int64_t *time)
6715{
6716 if (stream == NULL || frames == NULL || time == NULL) {
6717 return -EINVAL;
6718 }
6719 struct stream_in *in = (struct stream_in *)stream;
6720 int ret = -ENOSYS;
6721
6722 lock_input_stream(in);
6723 // note: ST sessions do not close the alsa pcm driver synchronously
6724 // on standby. Therefore, we may return an error even though the
6725 // pcm stream is still opened.
6726 if (in->standby) {
6727 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6728 "%s stream in standby but pcm not NULL for non ST session", __func__);
6729 goto exit;
6730 }
6731 if (in->pcm) {
6732 struct timespec timestamp;
6733 unsigned int avail;
6734 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6735 *frames = in->frames_read + avail;
6736 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6737 ret = 0;
6738 }
6739 }
6740exit:
6741 pthread_mutex_unlock(&in->lock);
6742 return ret;
6743}
6744
Carter Hsu2e429db2019-05-14 18:50:52 +08006745static int in_update_effect_list(bool add, effect_handle_t effect,
6746 struct listnode *head)
6747{
6748 struct listnode *node;
6749 struct in_effect_list *elist = NULL;
6750 struct in_effect_list *target = NULL;
6751 int ret = 0;
6752
6753 if (!head)
6754 return ret;
6755
6756 list_for_each(node, head) {
6757 elist = node_to_item(node, struct in_effect_list, list);
6758 if (elist->handle == effect) {
6759 target = elist;
6760 break;
6761 }
6762 }
6763
6764 if (add) {
6765 if (target) {
6766 ALOGD("effect %p already exist", effect);
6767 return ret;
6768 }
6769
6770 target = (struct in_effect_list *)
6771 calloc(1, sizeof(struct in_effect_list));
6772
6773 if (!target) {
6774 ALOGE("%s:fail to allocate memory", __func__);
6775 return -ENOMEM;
6776 }
6777
6778 target->handle = effect;
6779 list_add_tail(head, &target->list);
6780 } else {
6781 if (target) {
6782 list_remove(&target->list);
6783 free(target);
6784 }
6785 }
6786
6787 return ret;
6788}
6789
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006790static int add_remove_audio_effect(const struct audio_stream *stream,
6791 effect_handle_t effect,
6792 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006793{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006794 struct stream_in *in = (struct stream_in *)stream;
6795 int status = 0;
6796 effect_descriptor_t desc;
6797
6798 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006799 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6800
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006801 if (status != 0)
6802 return status;
6803
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006804 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006805 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006806 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08006807 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
6808 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006809 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08006810
6811 in_update_effect_list(enable, effect, &in->aec_list);
6812 enable = !list_empty(&in->aec_list);
6813 if (enable == in->enable_aec)
6814 goto exit;
6815
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006816 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006817 ALOGD("AEC enable %d", enable);
6818
Aalique Grahame22e49102018-12-18 14:23:57 -08006819 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6820 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6821 in->dev->enable_voicerx = enable;
6822 struct audio_usecase *usecase;
6823 struct listnode *node;
6824 list_for_each(node, &in->dev->usecase_list) {
6825 usecase = node_to_item(node, struct audio_usecase, list);
6826 if (usecase->type == PCM_PLAYBACK)
6827 select_devices(in->dev, usecase->id);
6828 }
6829 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006830 if (!in->standby) {
6831 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6832 select_devices(in->dev, in->usecase);
6833 }
6834
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006835 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006836 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
6837
6838 in_update_effect_list(enable, effect, &in->ns_list);
6839 enable = !list_empty(&in->ns_list);
6840 if (enable == in->enable_ns)
6841 goto exit;
6842
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006843 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006844 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006845 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006846 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6847 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006848 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6849 select_devices(in->dev, in->usecase);
6850 } else
6851 select_devices(in->dev, in->usecase);
6852 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006853 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006854exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006855 pthread_mutex_unlock(&in->dev->lock);
6856 pthread_mutex_unlock(&in->lock);
6857
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006858 return 0;
6859}
6860
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006861static int in_add_audio_effect(const struct audio_stream *stream,
6862 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006863{
Eric Laurent994a6932013-07-17 11:51:42 -07006864 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006865 return add_remove_audio_effect(stream, effect, true);
6866}
6867
6868static int in_remove_audio_effect(const struct audio_stream *stream,
6869 effect_handle_t effect)
6870{
Eric Laurent994a6932013-07-17 11:51:42 -07006871 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006872 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006873}
6874
Derek Chenf939fb72018-11-13 13:34:41 -08006875streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6876 audio_io_handle_t input)
6877{
6878 struct listnode *node;
6879
6880 list_for_each(node, &dev->active_inputs_list) {
6881 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6882 streams_input_ctxt_t,
6883 list);
6884 if (in_ctxt->input->capture_handle == input) {
6885 return in_ctxt;
6886 }
6887 }
6888 return NULL;
6889}
6890
6891streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6892 audio_io_handle_t output)
6893{
6894 struct listnode *node;
6895
6896 list_for_each(node, &dev->active_outputs_list) {
6897 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6898 streams_output_ctxt_t,
6899 list);
6900 if (out_ctxt->output->handle == output) {
6901 return out_ctxt;
6902 }
6903 }
6904 return NULL;
6905}
6906
Haynes Mathew George16081042017-05-31 17:16:49 -07006907static int in_stop(const struct audio_stream_in* stream)
6908{
6909 struct stream_in *in = (struct stream_in *)stream;
6910 struct audio_device *adev = in->dev;
6911
6912 int ret = -ENOSYS;
6913 ALOGV("%s", __func__);
6914 pthread_mutex_lock(&adev->lock);
6915 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6916 in->capture_started && in->pcm != NULL) {
6917 pcm_stop(in->pcm);
6918 ret = stop_input_stream(in);
6919 in->capture_started = false;
6920 }
6921 pthread_mutex_unlock(&adev->lock);
6922 return ret;
6923}
6924
6925static int in_start(const struct audio_stream_in* stream)
6926{
6927 struct stream_in *in = (struct stream_in *)stream;
6928 struct audio_device *adev = in->dev;
6929 int ret = -ENOSYS;
6930
6931 ALOGV("%s in %p", __func__, in);
6932 pthread_mutex_lock(&adev->lock);
6933 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6934 !in->capture_started && in->pcm != NULL) {
6935 if (!in->capture_started) {
6936 ret = start_input_stream(in);
6937 if (ret == 0) {
6938 in->capture_started = true;
6939 }
6940 }
6941 }
6942 pthread_mutex_unlock(&adev->lock);
6943 return ret;
6944}
6945
Phil Burke0a86d12019-02-16 22:28:11 -08006946// Read offset for the positional timestamp from a persistent vendor property.
6947// This is to workaround apparent inaccuracies in the timing information that
6948// is used by the AAudio timing model. The inaccuracies can cause glitches.
6949static int64_t in_get_mmap_time_offset() {
6950 const int32_t kDefaultOffsetMicros = 0;
6951 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006952 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006953 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6954 return mmap_time_offset_micros * (int64_t)1000;
6955}
6956
Haynes Mathew George16081042017-05-31 17:16:49 -07006957static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6958 int32_t min_size_frames,
6959 struct audio_mmap_buffer_info *info)
6960{
6961 struct stream_in *in = (struct stream_in *)stream;
6962 struct audio_device *adev = in->dev;
6963 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006964 unsigned int offset1 = 0;
6965 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006966 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006967 uint32_t mmap_size = 0;
6968 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006969
6970 pthread_mutex_lock(&adev->lock);
6971 ALOGV("%s in %p", __func__, in);
6972
Sharad Sanglec6f32552018-05-04 16:15:38 +05306973 if (CARD_STATUS_OFFLINE == in->card_status||
6974 CARD_STATUS_OFFLINE == adev->card_status) {
6975 ALOGW("in->card_status or adev->card_status offline, try again");
6976 ret = -EIO;
6977 goto exit;
6978 }
6979
Haynes Mathew George16081042017-05-31 17:16:49 -07006980 if (info == NULL || min_size_frames == 0) {
6981 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6982 ret = -EINVAL;
6983 goto exit;
6984 }
6985 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6986 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6987 ALOGV("%s in %p", __func__, in);
6988 ret = -ENOSYS;
6989 goto exit;
6990 }
6991 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6992 if (in->pcm_device_id < 0) {
6993 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6994 __func__, in->pcm_device_id, in->usecase);
6995 ret = -EINVAL;
6996 goto exit;
6997 }
6998
6999 adjust_mmap_period_count(&in->config, min_size_frames);
7000
7001 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
7002 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
7003 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
7004 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05307005 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05307006 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
7007 in->card_status = CARD_STATUS_OFFLINE;
7008 adev->card_status = CARD_STATUS_OFFLINE;
7009 ret = -EIO;
7010 goto exit;
7011 }
7012
Haynes Mathew George16081042017-05-31 17:16:49 -07007013 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
7014 step = "open";
7015 ret = -ENODEV;
7016 goto exit;
7017 }
7018
7019 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
7020 if (ret < 0) {
7021 step = "begin";
7022 goto exit;
7023 }
Haynes Mathew George16081042017-05-31 17:16:49 -07007024
Arun Mirpuri5d170872019-03-26 13:21:31 -07007025 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
7026 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
7027 info->burst_size_frames = in->config.period_size;
7028 ret = platform_get_mmap_data_fd(adev->platform,
7029 in->pcm_device_id, 1 /*capture*/,
7030 &info->shared_memory_fd,
7031 &mmap_size);
7032 if (ret < 0) {
7033 // Fall back to non exclusive mode
7034 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
7035 } else {
7036 if (mmap_size < buffer_size) {
7037 step = "mmap";
7038 goto exit;
7039 }
7040 // FIXME: indicate exclusive mode support by returning a negative buffer size
7041 info->buffer_size_frames *= -1;
7042 }
7043
7044 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07007045
7046 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
7047 if (ret < 0) {
7048 step = "commit";
7049 goto exit;
7050 }
7051
Phil Burke0a86d12019-02-16 22:28:11 -08007052 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
7053
Haynes Mathew George16081042017-05-31 17:16:49 -07007054 in->standby = false;
7055 ret = 0;
7056
7057 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
7058 __func__, info->shared_memory_address, info->buffer_size_frames);
7059
7060exit:
7061 if (ret != 0) {
7062 if (in->pcm == NULL) {
7063 ALOGE("%s: %s - %d", __func__, step, ret);
7064 } else {
7065 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
7066 pcm_close(in->pcm);
7067 in->pcm = NULL;
7068 }
7069 }
7070 pthread_mutex_unlock(&adev->lock);
7071 return ret;
7072}
7073
7074static int in_get_mmap_position(const struct audio_stream_in *stream,
7075 struct audio_mmap_position *position)
7076{
7077 struct stream_in *in = (struct stream_in *)stream;
7078 ALOGVV("%s", __func__);
7079 if (position == NULL) {
7080 return -EINVAL;
7081 }
7082 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
7083 return -ENOSYS;
7084 }
7085 if (in->pcm == NULL) {
7086 return -ENOSYS;
7087 }
7088 struct timespec ts = { 0, 0 };
7089 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
7090 if (ret < 0) {
7091 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
7092 return ret;
7093 }
Phil Burke0a86d12019-02-16 22:28:11 -08007094 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
7095 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07007096 return 0;
7097}
7098
Naresh Tannirudcb47c52018-06-25 16:23:32 +05307099static int in_get_active_microphones(const struct audio_stream_in *stream,
7100 struct audio_microphone_characteristic_t *mic_array,
7101 size_t *mic_count) {
7102 struct stream_in *in = (struct stream_in *)stream;
7103 struct audio_device *adev = in->dev;
7104 ALOGVV("%s", __func__);
7105
7106 lock_input_stream(in);
7107 pthread_mutex_lock(&adev->lock);
7108 int ret = platform_get_active_microphones(adev->platform,
7109 audio_channel_count_from_in_mask(in->channel_mask),
7110 in->usecase, mic_array, mic_count);
7111 pthread_mutex_unlock(&adev->lock);
7112 pthread_mutex_unlock(&in->lock);
7113
7114 return ret;
7115}
7116
7117static int adev_get_microphones(const struct audio_hw_device *dev,
7118 struct audio_microphone_characteristic_t *mic_array,
7119 size_t *mic_count) {
7120 struct audio_device *adev = (struct audio_device *)dev;
7121 ALOGVV("%s", __func__);
7122
7123 pthread_mutex_lock(&adev->lock);
7124 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7125 pthread_mutex_unlock(&adev->lock);
7126
7127 return ret;
7128}
juyuchendb308c22019-01-21 11:57:17 -07007129
7130static void in_update_sink_metadata(struct audio_stream_in *stream,
7131 const struct sink_metadata *sink_metadata) {
7132
7133 if (stream == NULL
7134 || sink_metadata == NULL
7135 || sink_metadata->tracks == NULL) {
7136 return;
7137 }
7138
7139 int error = 0;
7140 struct stream_in *in = (struct stream_in *)stream;
7141 struct audio_device *adev = in->dev;
7142 audio_devices_t device = AUDIO_DEVICE_NONE;
7143
7144 if (sink_metadata->track_count != 0)
7145 device = sink_metadata->tracks->dest_device;
7146
7147 lock_input_stream(in);
7148 pthread_mutex_lock(&adev->lock);
7149 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
7150
7151 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
7152 && device != AUDIO_DEVICE_NONE
7153 && adev->voice_tx_output != NULL) {
7154 /* Use the rx device from afe-proxy record to route voice call because
7155 there is no routing if tx device is on primary hal and rx device
7156 is on other hal during voice call. */
7157 adev->voice_tx_output->devices = device;
7158
7159 if (!voice_is_call_state_active(adev)) {
7160 if (adev->mode == AUDIO_MODE_IN_CALL) {
7161 adev->current_call_output = adev->voice_tx_output;
7162 error = voice_start_call(adev);
7163 if (error != 0)
7164 ALOGE("%s: start voice call failed %d", __func__, error);
7165 }
7166 } else {
7167 adev->current_call_output = adev->voice_tx_output;
7168 voice_update_devices_for_all_voice_usecases(adev);
7169 }
7170 }
7171
7172 pthread_mutex_unlock(&adev->lock);
7173 pthread_mutex_unlock(&in->lock);
7174}
7175
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307176int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007177 audio_io_handle_t handle,
7178 audio_devices_t devices,
7179 audio_output_flags_t flags,
7180 struct audio_config *config,
7181 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007182 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007183{
7184 struct audio_device *adev = (struct audio_device *)dev;
7185 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307186 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007187 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007188 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307189 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007190 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7191 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7192 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7193 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007194 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007195 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7196 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007197 bool force_haptic_path =
7198 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007199 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007200
kunleizdff872d2018-08-20 14:40:33 +08007201 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007202 is_usb_dev = false;
7203 devices = AUDIO_DEVICE_OUT_SPEAKER;
7204 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7205 __func__, devices);
7206 }
7207
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007208 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307209
Rahul Sharma99770982019-03-06 17:05:26 +05307210 pthread_mutex_lock(&adev->lock);
7211 if (out_get_stream(adev, handle) != NULL) {
7212 ALOGW("%s, output stream already opened", __func__);
7213 ret = -EEXIST;
7214 }
7215 pthread_mutex_unlock(&adev->lock);
7216 if (ret)
7217 return ret;
7218
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007219 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7220
Mingming Yin3a941d42016-02-17 18:08:05 -08007221 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007222 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7223 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307224
7225
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007226 if (!out) {
7227 return -ENOMEM;
7228 }
7229
Haynes Mathew George204045b2015-02-25 20:32:03 -08007230 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007231 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307232 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007233 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007234 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7235
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007236 if (devices == AUDIO_DEVICE_NONE)
7237 devices = AUDIO_DEVICE_OUT_SPEAKER;
7238
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007239 out->flags = flags;
7240 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007241 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007242 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007243 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307244 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307245 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7246 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7247 else
7248 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007249 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007250 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007251 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307252 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307253 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307254 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007255 out->hal_output_suspend_supported = 0;
7256 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307257 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307258 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307259 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007260
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307261 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307262 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007263 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7264
Aalique Grahame22e49102018-12-18 14:23:57 -08007265 if (direct_dev &&
7266 (audio_is_linear_pcm(out->format) ||
7267 config->format == AUDIO_FORMAT_DEFAULT) &&
7268 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7269 audio_format_t req_format = config->format;
7270 audio_channel_mask_t req_channel_mask = config->channel_mask;
7271 uint32_t req_sample_rate = config->sample_rate;
7272
7273 pthread_mutex_lock(&adev->lock);
7274 if (is_hdmi) {
7275 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7276 ret = read_hdmi_sink_caps(out);
7277 if (config->sample_rate == 0)
7278 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7279 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7280 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7281 if (config->format == AUDIO_FORMAT_DEFAULT)
7282 config->format = AUDIO_FORMAT_PCM_16_BIT;
7283 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007284 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7285 &config->format,
7286 &out->supported_formats[0],
7287 MAX_SUPPORTED_FORMATS,
7288 &config->channel_mask,
7289 &out->supported_channel_masks[0],
7290 MAX_SUPPORTED_CHANNEL_MASKS,
7291 &config->sample_rate,
7292 &out->supported_sample_rates[0],
7293 MAX_SUPPORTED_SAMPLE_RATES);
7294 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007295 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007296
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007297 pthread_mutex_unlock(&adev->lock);
7298 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007299 if (ret == -ENOSYS) {
7300 /* ignore and go with default */
7301 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007302 }
7303 // For MMAP NO IRQ, allow conversions in ADSP
7304 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7305 goto error_open;
7306 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007307 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007308 goto error_open;
7309 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007310
7311 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7312 config->sample_rate = req_sample_rate;
7313 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7314 config->channel_mask = req_channel_mask;
7315 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7316 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007317 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007318
7319 out->sample_rate = config->sample_rate;
7320 out->channel_mask = config->channel_mask;
7321 out->format = config->format;
7322 if (is_hdmi) {
7323 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7324 out->config = pcm_config_hdmi_multi;
7325 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7326 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7327 out->config = pcm_config_mmap_playback;
7328 out->stream.start = out_start;
7329 out->stream.stop = out_stop;
7330 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7331 out->stream.get_mmap_position = out_get_mmap_position;
7332 } else {
7333 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7334 out->config = pcm_config_hifi;
7335 }
7336
7337 out->config.rate = out->sample_rate;
7338 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7339 if (is_hdmi) {
7340 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7341 audio_bytes_per_sample(out->format));
7342 }
7343 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007344 }
7345
Derek Chenf6318be2017-06-12 17:16:24 -04007346 /* validate bus device address */
7347 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7348 /* extract car audio stream index */
7349 out->car_audio_stream =
7350 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7351 if (out->car_audio_stream < 0) {
7352 ALOGE("%s: invalid car audio stream %x",
7353 __func__, out->car_audio_stream);
7354 ret = -EINVAL;
7355 goto error_open;
7356 }
7357 /* save car audio stream and address for bus device */
7358 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
7359 ALOGV("%s: address %s, car_audio_stream %x",
7360 __func__, out->address, out->car_audio_stream);
7361 }
7362
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007363 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007364 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007365 if (!voice_extn_is_compress_voip_supported()) {
7366 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7367 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007368 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7369 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007370 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7371 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007372 out->volume_l = INVALID_OUT_VOLUME;
7373 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007374
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007375 out->config = default_pcm_config_voip_copp;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007376 out->config.rate = out->sample_rate;
Aniket Kumar Lata1e344f22019-06-19 17:09:01 -07007377 uint32_t channel_count =
7378 audio_channel_count_from_out_mask(out->channel_mask);
7379 uint32_t buffer_size = get_stream_buffer_size(DEFAULT_VOIP_BUF_DURATION_MS,
7380 out->sample_rate, out->format,
7381 channel_count, false);
7382 uint32_t frame_size = audio_bytes_per_sample(out->format) * channel_count;
7383 if (frame_size != 0)
7384 out->config.period_size = buffer_size / frame_size;
7385 else
7386 ALOGW("%s: frame size is 0 for format %#x", __func__, out->format);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007387 }
7388 } else {
7389 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7390 voice_extn_compress_voip_is_active(out->dev)) &&
7391 (voice_extn_compress_voip_is_config_supported(config))) {
7392 ret = voice_extn_compress_voip_open_output_stream(out);
7393 if (ret != 0) {
7394 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7395 __func__, ret);
7396 goto error_open;
7397 }
Sujin Panickerbd95e0a2019-09-16 18:28:06 +05307398 } else {
7399 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7400 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007401 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007402 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007403 } else if (audio_is_linear_pcm(out->format) &&
7404 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7405 out->channel_mask = config->channel_mask;
7406 out->sample_rate = config->sample_rate;
7407 out->format = config->format;
7408 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7409 // does this change?
7410 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7411 out->config.rate = config->sample_rate;
7412 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7413 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7414 audio_bytes_per_sample(config->format));
7415 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007416 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307417 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307418 pthread_mutex_lock(&adev->lock);
7419 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7420 pthread_mutex_unlock(&adev->lock);
7421
7422 // reject offload during card offline to allow
7423 // fallback to s/w paths
7424 if (offline) {
7425 ret = -ENODEV;
7426 goto error_open;
7427 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007428
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007429 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7430 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7431 ALOGE("%s: Unsupported Offload information", __func__);
7432 ret = -EINVAL;
7433 goto error_open;
7434 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007435
Atul Khare3fa6e542017-08-09 00:56:17 +05307436 if (config->offload_info.format == 0)
7437 config->offload_info.format = config->format;
7438 if (config->offload_info.sample_rate == 0)
7439 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007440
Mingming Yin90310102013-11-13 16:57:00 -08007441 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307442 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007443 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007444 ret = -EINVAL;
7445 goto error_open;
7446 }
7447
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007448 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7449 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7450 (audio_extn_passthru_is_passthrough_stream(out)) &&
7451 !((config->sample_rate == 48000) ||
7452 (config->sample_rate == 96000) ||
7453 (config->sample_rate == 192000))) {
7454 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7455 __func__, config->sample_rate, config->offload_info.format);
7456 ret = -EINVAL;
7457 goto error_open;
7458 }
7459
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007460 out->compr_config.codec = (struct snd_codec *)
7461 calloc(1, sizeof(struct snd_codec));
7462
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007463 if (!out->compr_config.codec) {
7464 ret = -ENOMEM;
7465 goto error_open;
7466 }
7467
Dhananjay Kumarac341582017-02-23 23:42:25 +05307468 out->stream.pause = out_pause;
7469 out->stream.resume = out_resume;
7470 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307471 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307472 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007473 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307474 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007475 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307476 } else {
7477 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7478 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007479 }
vivek mehta446c3962015-09-14 10:57:35 -07007480
Deeraj Somanfa377bf2019-02-06 12:57:59 +05307481 if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7482 ALOGD("%s: Setting latency mode to true", __func__);
7483 out->compr_config.codec->flags |= audio_extn_utils_get_perf_mode_flag();
7484 }
7485
vivek mehta446c3962015-09-14 10:57:35 -07007486 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007487 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7488 config->format == 0 && config->sample_rate == 0 &&
7489 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007490 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007491 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7492 } else {
7493 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7494 ret = -EEXIST;
7495 goto error_open;
7496 }
vivek mehta446c3962015-09-14 10:57:35 -07007497 }
7498
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007499 if (config->offload_info.channel_mask)
7500 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007501 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007502 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007503 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007504 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307505 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007506 ret = -EINVAL;
7507 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007508 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007509
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007510 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007511 out->sample_rate = config->offload_info.sample_rate;
7512
Mingming Yin3ee55c62014-08-04 14:23:35 -07007513 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007514
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307515 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307516 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307517 audio_extn_dolby_send_ddp_endp_params(adev);
7518 audio_extn_dolby_set_dmid(adev);
7519 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007520
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007521 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007522 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007523 out->compr_config.codec->bit_rate =
7524 config->offload_info.bit_rate;
7525 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307526 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007527 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307528 /* Update bit width only for non passthrough usecases.
7529 * For passthrough usecases, the output will always be opened @16 bit
7530 */
7531 if (!audio_extn_passthru_is_passthrough_stream(out))
7532 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307533
7534 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7535 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7536 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7537
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007538 /*TODO: Do we need to change it for passthrough */
7539 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007540
Manish Dewangana6fc5442015-08-24 20:30:31 +05307541 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7542 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307543 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307544 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307545 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7546 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307547
7548 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7549 AUDIO_FORMAT_PCM) {
7550
7551 /*Based on platform support, configure appropriate alsa format for corresponding
7552 *hal input format.
7553 */
7554 out->compr_config.codec->format = hal_format_to_alsa(
7555 config->offload_info.format);
7556
Ashish Jain83a6cc22016-06-28 14:34:17 +05307557 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307558 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307559 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307560
Dhananjay Kumarac341582017-02-23 23:42:25 +05307561 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307562 *hal input format and alsa format might differ based on platform support.
7563 */
7564 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307565 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307566
7567 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7568
Deeraj Soman65358ab2019-02-07 15:40:49 +05307569 if ((config->offload_info.duration_us >= MIN_OFFLOAD_BUFFER_DURATION_MS * 1000) &&
7570 (config->offload_info.duration_us <= MAX_OFFLOAD_BUFFER_DURATION_MS * 1000))
7571 out->info.duration_us = (int64_t)config->offload_info.duration_us;
7572
Ashish Jainf1eaa582016-05-23 20:54:24 +05307573 /* Check if alsa session is configured with the same format as HAL input format,
7574 * if not then derive correct fragment size needed to accomodate the
7575 * conversion of HAL input format to alsa format.
7576 */
7577 audio_extn_utils_update_direct_pcm_fragment_size(out);
7578
7579 /*if hal input and output fragment size is different this indicates HAL input format is
7580 *not same as the alsa format
7581 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307582 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307583 /*Allocate a buffer to convert input data to the alsa configured format.
7584 *size of convert buffer is equal to the size required to hold one fragment size
7585 *worth of pcm data, this is because flinger does not write more than fragment_size
7586 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307587 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7588 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307589 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7590 ret = -ENOMEM;
7591 goto error_open;
7592 }
7593 }
7594 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7595 out->compr_config.fragment_size =
7596 audio_extn_passthru_get_buffer_size(&config->offload_info);
7597 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7598 } else {
7599 out->compr_config.fragment_size =
7600 platform_get_compress_offload_buffer_size(&config->offload_info);
7601 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7602 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007603
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307604 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7605 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7606 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007607 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307608 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007609
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307610 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7611 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7612 }
7613
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007614 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7615 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007616
Manish Dewangan69426c82017-01-30 17:35:36 +05307617 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7618 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7619 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7620 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7621 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7622 } else {
7623 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7624 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007625
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307626 memset(&out->channel_map_param, 0,
7627 sizeof(struct audio_out_channel_map_param));
7628
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007629 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307630 out->send_next_track_params = false;
7631 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007632 out->offload_state = OFFLOAD_STATE_IDLE;
7633 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007634 out->writeAt.tv_sec = 0;
7635 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007636
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007637 audio_extn_dts_create_state_notifier_node(out->usecase);
7638
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007639 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7640 __func__, config->offload_info.version,
7641 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307642
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307643 /* Check if DSD audio format is supported in codec
7644 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307645 */
7646
7647 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307648 (!platform_check_codec_dsd_support(adev->platform) ||
7649 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307650 ret = -EINVAL;
7651 goto error_open;
7652 }
7653
Ashish Jain5106d362016-05-11 19:23:33 +05307654 /* Disable gapless if any of the following is true
7655 * passthrough playback
7656 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307657 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307658 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307659 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307660 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007661 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307662 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307663 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307664 check_and_set_gapless_mode(adev, false);
7665 } else
7666 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007667
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307668 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007669 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7670 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307671 if (config->format == AUDIO_FORMAT_DSD) {
7672 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7673 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7674 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007675
7676 create_offload_callback_thread(out);
7677
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007678 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007679 switch (config->sample_rate) {
7680 case 0:
7681 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7682 break;
7683 case 8000:
7684 case 16000:
7685 case 48000:
7686 out->sample_rate = config->sample_rate;
7687 break;
7688 default:
7689 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7690 config->sample_rate);
7691 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7692 ret = -EINVAL;
7693 goto error_open;
7694 }
7695 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7696 switch (config->channel_mask) {
7697 case AUDIO_CHANNEL_NONE:
7698 case AUDIO_CHANNEL_OUT_STEREO:
7699 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7700 break;
7701 default:
7702 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7703 config->channel_mask);
7704 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7705 ret = -EINVAL;
7706 goto error_open;
7707 }
7708 switch (config->format) {
7709 case AUDIO_FORMAT_DEFAULT:
7710 case AUDIO_FORMAT_PCM_16_BIT:
7711 out->format = AUDIO_FORMAT_PCM_16_BIT;
7712 break;
7713 default:
7714 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7715 config->format);
7716 config->format = AUDIO_FORMAT_PCM_16_BIT;
7717 ret = -EINVAL;
7718 goto error_open;
7719 }
7720
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307721 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007722 if (ret != 0) {
7723 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007724 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007725 goto error_open;
7726 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007727 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007728 switch (config->sample_rate) {
7729 case 0:
7730 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7731 break;
7732 case 8000:
7733 case 16000:
7734 case 48000:
7735 out->sample_rate = config->sample_rate;
7736 break;
7737 default:
7738 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7739 config->sample_rate);
7740 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7741 ret = -EINVAL;
7742 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007743 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007744 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7745 switch (config->channel_mask) {
7746 case AUDIO_CHANNEL_NONE:
7747 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7748 break;
7749 case AUDIO_CHANNEL_OUT_STEREO:
7750 out->channel_mask = config->channel_mask;
7751 break;
7752 default:
7753 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7754 config->channel_mask);
7755 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7756 ret = -EINVAL;
7757 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007758 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007759 switch (config->format) {
7760 case AUDIO_FORMAT_DEFAULT:
7761 out->format = AUDIO_FORMAT_PCM_16_BIT;
7762 break;
7763 case AUDIO_FORMAT_PCM_16_BIT:
7764 out->format = config->format;
7765 break;
7766 default:
7767 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7768 config->format);
7769 config->format = AUDIO_FORMAT_PCM_16_BIT;
7770 ret = -EINVAL;
7771 break;
7772 }
7773 if (ret != 0)
7774 goto error_open;
7775
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007776 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7777 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007778 out->config.rate = out->sample_rate;
7779 out->config.channels =
7780 audio_channel_count_from_out_mask(out->channel_mask);
7781 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007782 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007783 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307784 unsigned int channels = 0;
7785 /*Update config params to default if not set by the caller*/
7786 if (config->sample_rate == 0)
7787 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7788 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7789 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7790 if (config->format == AUDIO_FORMAT_DEFAULT)
7791 config->format = AUDIO_FORMAT_PCM_16_BIT;
7792
7793 channels = audio_channel_count_from_out_mask(out->channel_mask);
7794
Varun Balaraje49253e2017-07-06 19:48:56 +05307795 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7796 out->usecase = get_interactive_usecase(adev);
7797 out->config = pcm_config_low_latency;
7798 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307799 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007800 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7801 out->flags);
7802 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007803 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7804 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7805 out->config = pcm_config_mmap_playback;
7806 out->stream.start = out_start;
7807 out->stream.stop = out_stop;
7808 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7809 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307810 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7811 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007812 out->hal_output_suspend_supported =
7813 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7814 out->dynamic_pm_qos_config_supported =
7815 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7816 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007817 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7818 } else {
7819 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7820 //the mixer path will be a string similar to "low-latency-playback resume"
7821 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7822 strlcat(out->pm_qos_mixer_path,
7823 " resume", MAX_MIXER_PATH_LEN);
7824 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7825 out->pm_qos_mixer_path);
7826 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307827 out->config = pcm_config_low_latency;
7828 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7829 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7830 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307831 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7832 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7833 if (out->config.period_size <= 0) {
7834 ALOGE("Invalid configuration period size is not valid");
7835 ret = -EINVAL;
7836 goto error_open;
7837 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007838 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7839 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7840 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007841 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7842 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7843 out->config = pcm_config_haptics_audio;
7844 if (force_haptic_path)
7845 adev->haptics_config = pcm_config_haptics_audio;
7846 else
7847 adev->haptics_config = pcm_config_haptics;
7848
7849 out->config.channels =
7850 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7851
7852 if (force_haptic_path) {
7853 out->config.channels = 1;
7854 adev->haptics_config.channels = 1;
7855 } else
7856 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Derek Chenf6318be2017-06-12 17:16:24 -04007857 } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7858 ret = audio_extn_auto_hal_open_output_stream(out);
7859 if (ret) {
7860 ALOGE("%s: Failed to open output stream for bus device", __func__);
7861 ret = -EINVAL;
7862 goto error_open;
7863 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307864 } else {
7865 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007866 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7867 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307868 }
7869 out->hal_ip_format = format = out->format;
7870 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7871 out->hal_op_format = pcm_format_to_hal(out->config.format);
7872 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7873 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007874 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307875 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307876 if (out->hal_ip_format != out->hal_op_format) {
7877 uint32_t buffer_size = out->config.period_size *
7878 format_to_bitwidth_table[out->hal_op_format] *
7879 out->config.channels;
7880 out->convert_buffer = calloc(1, buffer_size);
7881 if (out->convert_buffer == NULL){
7882 ALOGE("Allocation failed for convert buffer for size %d",
7883 out->compr_config.fragment_size);
7884 ret = -ENOMEM;
7885 goto error_open;
7886 }
7887 ALOGD("Convert buffer allocated of size %d", buffer_size);
7888 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007889 }
7890
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007891 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7892 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307893
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007894 /* TODO remove this hardcoding and check why width is zero*/
7895 if (out->bit_width == 0)
7896 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307897 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007898 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007899 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307900 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307901 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007902 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007903 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7904 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007905 if(adev->primary_output == NULL)
7906 adev->primary_output = out;
7907 else {
7908 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007909 ret = -EEXIST;
7910 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007911 }
7912 }
7913
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007914 /* Check if this usecase is already existing */
7915 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007916 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7917 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007918 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007919 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007920 ret = -EEXIST;
7921 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007922 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007923
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007924 pthread_mutex_unlock(&adev->lock);
7925
7926 out->stream.common.get_sample_rate = out_get_sample_rate;
7927 out->stream.common.set_sample_rate = out_set_sample_rate;
7928 out->stream.common.get_buffer_size = out_get_buffer_size;
7929 out->stream.common.get_channels = out_get_channels;
7930 out->stream.common.get_format = out_get_format;
7931 out->stream.common.set_format = out_set_format;
7932 out->stream.common.standby = out_standby;
7933 out->stream.common.dump = out_dump;
7934 out->stream.common.set_parameters = out_set_parameters;
7935 out->stream.common.get_parameters = out_get_parameters;
7936 out->stream.common.add_audio_effect = out_add_audio_effect;
7937 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7938 out->stream.get_latency = out_get_latency;
7939 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007940#ifdef NO_AUDIO_OUT
7941 out->stream.write = out_write_for_no_output;
7942#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007943 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007944#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007945 out->stream.get_render_position = out_get_render_position;
7946 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007947 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007948
Haynes Mathew George16081042017-05-31 17:16:49 -07007949 if (out->realtime)
7950 out->af_period_multiplier = af_period_multiplier;
7951 else
7952 out->af_period_multiplier = 1;
7953
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007954 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007955 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007956 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007957
7958 config->format = out->stream.common.get_format(&out->stream.common);
7959 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7960 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307961 register_format(out->format, out->supported_formats);
7962 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7963 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007964
Aalique Grahame22e49102018-12-18 14:23:57 -08007965 out->error_log = error_log_create(
7966 ERROR_LOG_ENTRIES,
7967 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7968
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307969 /*
7970 By locking output stream before registering, we allow the callback
7971 to update stream's state only after stream's initial state is set to
7972 adev state.
7973 */
7974 lock_output_stream(out);
7975 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7976 pthread_mutex_lock(&adev->lock);
7977 out->card_status = adev->card_status;
7978 pthread_mutex_unlock(&adev->lock);
7979 pthread_mutex_unlock(&out->lock);
7980
Aalique Grahame22e49102018-12-18 14:23:57 -08007981 stream_app_type_cfg_init(&out->app_type_cfg);
7982
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007983 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307984 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007985 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007986
7987 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7988 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7989 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007990 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307991 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007992 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007993 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307994 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
7995 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007996 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7997 out->usecase, PCM_PLAYBACK);
7998 hdlr_stream_cfg.flags = out->flags;
7999 hdlr_stream_cfg.type = PCM_PLAYBACK;
8000 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
8001 &hdlr_stream_cfg);
8002 if (ret) {
8003 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
8004 out->adsp_hdlr_stream_handle = NULL;
8005 }
8006 }
Gangadhar Sb0210342019-02-22 17:39:41 +05308007 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
8008 is_direct_passthough, false);
8009 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
8010 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07008011 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07008012 if (ret < 0) {
8013 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
8014 out->ip_hdlr_handle = NULL;
8015 }
8016 }
Derek Chenf939fb72018-11-13 13:34:41 -08008017
8018 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
8019 calloc(1, sizeof(streams_output_ctxt_t));
8020 if (out_ctxt == NULL) {
8021 ALOGE("%s fail to allocate output ctxt", __func__);
8022 ret = -ENOMEM;
8023 goto error_open;
8024 }
8025 out_ctxt->output = out;
8026
8027 pthread_mutex_lock(&adev->lock);
8028 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
8029 pthread_mutex_unlock(&adev->lock);
8030
Eric Laurent994a6932013-07-17 11:51:42 -07008031 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008032 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008033
8034error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05308035 if (out->convert_buffer)
8036 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07008037 free(out);
8038 *stream_out = NULL;
8039 ALOGD("%s: exit: ret %d", __func__, ret);
8040 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008041}
8042
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308043void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008044 struct audio_stream_out *stream)
8045{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008046 struct stream_out *out = (struct stream_out *)stream;
8047 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008048 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008049
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008050 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308051
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308052 // must deregister from sndmonitor first to prevent races
8053 // between the callback and close_stream
8054 audio_extn_snd_mon_unregister_listener(out);
8055
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008056 /* close adsp hdrl session before standby */
8057 if (out->adsp_hdlr_stream_handle) {
8058 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
8059 if (ret)
8060 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
8061 out->adsp_hdlr_stream_handle = NULL;
8062 }
8063
Manish Dewangan21a850a2017-08-14 12:03:55 +05308064 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07008065 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
8066 out->ip_hdlr_handle = NULL;
8067 }
8068
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008069 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308070 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008071 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308072 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308073 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008074 if(ret != 0)
8075 ALOGE("%s: Compress voip output cannot be closed, error:%d",
8076 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008077 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008078 out_standby(&stream->common);
8079
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008080 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08008081 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008082 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008083 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008084 if (out->compr_config.codec != NULL)
8085 free(out->compr_config.codec);
8086 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008087
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308088 out->a2dp_compress_mute = false;
8089
Varun Balaraje49253e2017-07-06 19:48:56 +05308090 if (is_interactive_usecase(out->usecase))
8091 free_interactive_usecase(adev, out->usecase);
8092
Ashish Jain83a6cc22016-06-28 14:34:17 +05308093 if (out->convert_buffer != NULL) {
8094 free(out->convert_buffer);
8095 out->convert_buffer = NULL;
8096 }
8097
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008098 if (adev->voice_tx_output == out)
8099 adev->voice_tx_output = NULL;
8100
Aalique Grahame22e49102018-12-18 14:23:57 -08008101 error_log_destroy(out->error_log);
8102 out->error_log = NULL;
8103
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05308104 if (adev->primary_output == out)
8105 adev->primary_output = NULL;
8106
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07008107 pthread_cond_destroy(&out->cond);
8108 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08008109
8110 pthread_mutex_lock(&adev->lock);
8111 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
8112 if (out_ctxt != NULL) {
8113 list_remove(&out_ctxt->list);
8114 free(out_ctxt);
8115 } else {
8116 ALOGW("%s, output stream already closed", __func__);
8117 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008118 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08008119 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07008120 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008121}
8122
8123static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
8124{
8125 struct audio_device *adev = (struct audio_device *)dev;
8126 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008127 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008128 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008129 int ret;
8130 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08008131 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008132 struct listnode *node;
8133 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008134
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008135 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008136 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008137
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308138 if (!parms)
8139 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308140
Derek Chen6f293672019-04-01 01:40:24 -07008141 /* notify adev and input/output streams on the snd card status */
8142 adev_snd_mon_cb((void *)adev, parms);
8143
8144 list_for_each(node, &adev->active_outputs_list) {
8145 streams_output_ctxt_t *out_ctxt = node_to_item(node,
8146 streams_output_ctxt_t,
8147 list);
8148 out_snd_mon_cb((void *)out_ctxt->output, parms);
8149 }
8150
8151 list_for_each(node, &adev->active_inputs_list) {
8152 streams_input_ctxt_t *in_ctxt = node_to_item(node,
8153 streams_input_ctxt_t,
8154 list);
8155 in_snd_mon_cb((void *)in_ctxt->input, parms);
8156 }
8157
Zhou Songd6d71752019-05-21 18:08:51 +08008158 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308159 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8160 if (ret >= 0) {
8161 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008162 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308163 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008164 } else {
Zhou Songd304a912019-07-19 12:28:31 +08008165 ALOGD("sco is off, reset sco and route device to handset mic");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308166 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008167 audio_extn_sco_reset_configuration();
8168 list_for_each(node, &adev->usecase_list) {
8169 usecase = node_to_item(node, struct audio_usecase, list);
Zhou Songd304a912019-07-19 12:28:31 +08008170 if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
8171 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
Zhou Songd6d71752019-05-21 18:08:51 +08008172 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
8173 else
8174 continue;
8175 select_devices(adev, usecase->id);
8176 }
8177 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308178 }
8179
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008180 status = voice_set_parameters(adev, parms);
8181 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008182 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008183
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008184 status = platform_set_parameters(adev->platform, parms);
8185 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008186 goto done;
8187
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008188 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8189 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008190 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008191 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8192 adev->bluetooth_nrec = true;
8193 else
8194 adev->bluetooth_nrec = false;
8195 }
8196
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008197 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8198 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008199 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8200 adev->screen_off = false;
8201 else
8202 adev->screen_off = true;
Quinn Male70f20f32019-06-26 16:50:26 -07008203 audio_extn_sound_trigger_update_screen_status(adev->screen_off);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008204 }
8205
Eric Laurent4b084132018-10-19 17:33:43 -07008206 ret = str_parms_get_int(parms, "rotation", &val);
8207 if (ret >= 0) {
8208 bool reverse_speakers = false;
8209 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8210 switch (val) {
8211 // FIXME: note that the code below assumes that the speakers are in the correct placement
8212 // relative to the user when the device is rotated 90deg from its default rotation. This
8213 // assumption is device-specific, not platform-specific like this code.
8214 case 270:
8215 reverse_speakers = true;
8216 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8217 break;
8218 case 0:
8219 case 180:
8220 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8221 break;
8222 case 90:
8223 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8224 break;
8225 default:
8226 ALOGE("%s: unexpected rotation of %d", __func__, val);
8227 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008228 }
Eric Laurent4b084132018-10-19 17:33:43 -07008229 if (status == 0) {
8230 // check and set swap
8231 // - check if orientation changed and speaker active
8232 // - set rotation and cache the rotation value
8233 adev->camera_orientation =
8234 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8235 if (!audio_extn_is_maxx_audio_enabled())
8236 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8237 }
8238 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008239
Mingming Yin514a8bc2014-07-29 15:22:21 -07008240 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8241 if (ret >= 0) {
8242 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8243 adev->bt_wb_speech_enabled = true;
8244 else
8245 adev->bt_wb_speech_enabled = false;
8246 }
8247
Zhou Song12c29502019-03-16 10:37:18 +08008248 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8249 if (ret >= 0) {
8250 val = atoi(value);
8251 adev->swb_speech_mode = val;
8252 }
8253
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008254 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8255 if (ret >= 0) {
8256 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308257 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008258 if (audio_is_output_device(val) &&
8259 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008260 ALOGV("cache new ext disp type and edid");
8261 ret = platform_get_ext_disp_type(adev->platform);
8262 if (ret < 0) {
8263 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308264 } else {
8265 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008266 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308267 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008268 /*
8269 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8270 * Per AudioPolicyManager, USB device is higher priority than WFD.
8271 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8272 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8273 * starting voice call on USB
8274 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008275 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308276 if (ret >= 0)
8277 audio_extn_usb_add_device(device, atoi(value));
8278
Zhou Song6f862822017-11-06 17:27:57 +08008279 if (!audio_extn_usb_is_tunnel_supported()) {
8280 ALOGV("detected USB connect .. disable proxy");
8281 adev->allow_afe_proxy_usage = false;
8282 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008283 }
8284 }
8285
8286 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8287 if (ret >= 0) {
8288 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308289 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008290 /*
8291 * The HDMI / Displayport disconnect handling has been moved to
8292 * audio extension to ensure that its parameters are not
8293 * invalidated prior to updating sysfs of the disconnect event
8294 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8295 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308296 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008297 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308298 if (ret >= 0)
8299 audio_extn_usb_remove_device(device, atoi(value));
8300
Zhou Song6f862822017-11-06 17:27:57 +08008301 if (!audio_extn_usb_is_tunnel_supported()) {
8302 ALOGV("detected USB disconnect .. enable proxy");
8303 adev->allow_afe_proxy_usage = true;
8304 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008305 }
Manisha Agarwalc2188fb2019-05-27 10:00:29 +05308306 if (audio_is_a2dp_out_device(device)) {
8307 struct audio_usecase *usecase;
8308 struct listnode *node;
8309 list_for_each(node, &adev->usecase_list) {
8310 usecase = node_to_item(node, struct audio_usecase, list);
8311 if (PCM_PLAYBACK == usecase->type && usecase->stream.out &&
8312 (usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8313 usecase->stream.out->a2dp_compress_mute) {
8314 struct stream_out *out = usecase->stream.out;
8315 ALOGD("Unmuting the stream when Bt-A2dp disconnected and stream is mute");
8316 out->a2dp_compress_mute = false;
8317 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8318 }
8319 }
8320 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008321 }
8322
Aalique Grahame22e49102018-12-18 14:23:57 -08008323 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008324 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008325
8326 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008327 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308328 struct audio_usecase *usecase;
8329 struct listnode *node;
8330 list_for_each(node, &adev->usecase_list) {
8331 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308332 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07008333 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308334 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008335 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308336 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008337 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308338 audio_extn_a2dp_set_handoff_mode(true);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308339 ALOGD("Switching to speaker and muting the stream before select_devices");
8340 check_a2dp_restore_l(adev, usecase->stream.out, false);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308341 //force device switch to re configure encoder
8342 select_devices(adev, usecase->id);
Manisha Agarwalf1c3b6b2019-06-25 13:00:33 +05308343 ALOGD("Unmuting the stream after select_devices");
8344 usecase->stream.out->a2dp_compress_mute = false;
8345 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 +05308346 audio_extn_a2dp_set_handoff_mode(false);
8347 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308348 break;
8349 }
8350 }
8351 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008352
8353 //handle vr audio setparam
8354 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8355 value, sizeof(value));
8356 if (ret >= 0) {
8357 ALOGI("Setting vr mode to be %s", value);
8358 if (!strncmp(value, "true", 4)) {
8359 adev->vr_audio_mode_enabled = true;
8360 ALOGI("Setting vr mode to true");
8361 } else if (!strncmp(value, "false", 5)) {
8362 adev->vr_audio_mode_enabled = false;
8363 ALOGI("Setting vr mode to false");
8364 } else {
8365 ALOGI("wrong vr mode set");
8366 }
8367 }
8368
Eric Laurent4b084132018-10-19 17:33:43 -07008369 //FIXME: to be replaced by proper video capture properties API
8370 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8371 if (ret >= 0) {
8372 int camera_facing = CAMERA_FACING_BACK;
8373 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8374 camera_facing = CAMERA_FACING_FRONT;
8375 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8376 camera_facing = CAMERA_FACING_BACK;
8377 else {
8378 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8379 goto done;
8380 }
8381 adev->camera_orientation =
8382 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8383 struct audio_usecase *usecase;
8384 struct listnode *node;
8385 list_for_each(node, &adev->usecase_list) {
8386 usecase = node_to_item(node, struct audio_usecase, list);
8387 struct stream_in *in = usecase->stream.in;
8388 if (usecase->type == PCM_CAPTURE && in != NULL &&
8389 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8390 select_devices(adev, in->usecase);
8391 }
8392 }
8393 }
8394
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308395 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008396done:
8397 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008398 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308399error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008400 ALOGV("%s: exit with code(%d)", __func__, status);
8401 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008402}
8403
8404static char* adev_get_parameters(const struct audio_hw_device *dev,
8405 const char *keys)
8406{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308407 ALOGD("%s:%s", __func__, keys);
8408
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008409 struct audio_device *adev = (struct audio_device *)dev;
8410 struct str_parms *reply = str_parms_create();
8411 struct str_parms *query = str_parms_create_str(keys);
8412 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308413 char value[256] = {0};
8414 int ret = 0;
8415
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008416 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008417 if (reply) {
8418 str_parms_destroy(reply);
8419 }
8420 if (query) {
8421 str_parms_destroy(query);
8422 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008423 ALOGE("adev_get_parameters: failed to create query or reply");
8424 return NULL;
8425 }
8426
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008427 //handle vr audio getparam
8428
8429 ret = str_parms_get_str(query,
8430 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8431 value, sizeof(value));
8432
8433 if (ret >= 0) {
8434 bool vr_audio_enabled = false;
8435 pthread_mutex_lock(&adev->lock);
8436 vr_audio_enabled = adev->vr_audio_mode_enabled;
8437 pthread_mutex_unlock(&adev->lock);
8438
8439 ALOGI("getting vr mode to %d", vr_audio_enabled);
8440
8441 if (vr_audio_enabled) {
8442 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8443 "true");
8444 goto exit;
8445 } else {
8446 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8447 "false");
8448 goto exit;
8449 }
8450 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008451
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008452 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008453 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008454 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008455 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008456 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308457 pthread_mutex_unlock(&adev->lock);
8458
Naresh Tannirud7205b62014-06-20 02:54:48 +05308459exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008460 str = str_parms_to_str(reply);
8461 str_parms_destroy(query);
8462 str_parms_destroy(reply);
8463
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308464 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008465 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008466}
8467
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008468static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008469{
8470 return 0;
8471}
8472
8473static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8474{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008475 int ret;
8476 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008477
8478 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8479
Haynes Mathew George5191a852013-09-11 14:19:36 -07008480 pthread_mutex_lock(&adev->lock);
8481 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008482 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008483 pthread_mutex_unlock(&adev->lock);
8484 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008485}
8486
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008487static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8488 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008489{
8490 return -ENOSYS;
8491}
8492
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008493static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8494 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008495{
8496 return -ENOSYS;
8497}
8498
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008499static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8500 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008501{
8502 return -ENOSYS;
8503}
8504
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008505static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8506 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008507{
8508 return -ENOSYS;
8509}
8510
8511static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8512{
8513 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008514 struct listnode *node;
8515 struct audio_usecase *usecase = NULL;
8516 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008517
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008518 pthread_mutex_lock(&adev->lock);
8519 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008520 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008521 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008522 if (voice_is_in_call(adev) &&
8523 (mode == AUDIO_MODE_NORMAL ||
8524 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008525 list_for_each(node, &adev->usecase_list) {
8526 usecase = node_to_item(node, struct audio_usecase, list);
8527 if (usecase->type == VOICE_CALL)
8528 break;
8529 }
8530 if (usecase &&
8531 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8532 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8533 true);
8534 if (ret != 0) {
8535 /* default service interval was successfully updated,
8536 reopen USB backend with new service interval */
8537 check_usecases_codec_backend(adev,
8538 usecase,
8539 usecase->out_snd_device);
8540 }
8541 }
8542
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008543 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008544 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008545 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008546 // restore device for other active usecases after stop call
8547 list_for_each(node, &adev->usecase_list) {
8548 usecase = node_to_item(node, struct audio_usecase, list);
8549 select_devices(adev, usecase->id);
8550 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008551 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008552 }
8553 pthread_mutex_unlock(&adev->lock);
8554 return 0;
8555}
8556
8557static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8558{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008559 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008560 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008561
8562 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008563 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008564 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008565
Derek Chend2530072014-11-24 12:39:14 -08008566 if (adev->ext_hw_plugin)
8567 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008568
8569 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008570 pthread_mutex_unlock(&adev->lock);
8571
8572 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008573}
8574
8575static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8576{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008577 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008578 return 0;
8579}
8580
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008581static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008582 const struct audio_config *config)
8583{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008584 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008585
Aalique Grahame22e49102018-12-18 14:23:57 -08008586 /* Don't know if USB HIFI in this context so use true to be conservative */
8587 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8588 true /*is_usb_hifi */) != 0)
8589 return 0;
8590
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008591 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8592 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008593}
8594
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008595static bool adev_input_allow_hifi_record(struct audio_device *adev,
8596 audio_devices_t devices,
8597 audio_input_flags_t flags,
8598 audio_source_t source) {
8599 const bool allowed = true;
8600
8601 if (!audio_is_usb_in_device(devices))
8602 return !allowed;
8603
8604 switch (flags) {
8605 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008606 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008607 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8608 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008609 default:
8610 return !allowed;
8611 }
8612
8613 switch (source) {
8614 case AUDIO_SOURCE_DEFAULT:
8615 case AUDIO_SOURCE_MIC:
8616 case AUDIO_SOURCE_UNPROCESSED:
8617 break;
8618 default:
8619 return !allowed;
8620 }
8621
8622 switch (adev->mode) {
8623 case 0:
8624 break;
8625 default:
8626 return !allowed;
8627 }
8628
8629 return allowed;
8630}
8631
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008632static int adev_update_voice_comm_input_stream(struct stream_in *in,
8633 struct audio_config *config)
8634{
8635 bool valid_rate = (config->sample_rate == 8000 ||
8636 config->sample_rate == 16000 ||
8637 config->sample_rate == 32000 ||
8638 config->sample_rate == 48000);
8639 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8640
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008641 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008642 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008643 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8644 in->config = default_pcm_config_voip_copp;
8645 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8646 DEFAULT_VOIP_BUF_DURATION_MS,
8647 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008648 } else {
8649 ALOGW("%s No valid input in voip, use defaults"
8650 "sample rate %u, channel mask 0x%X",
8651 __func__, config->sample_rate, in->channel_mask);
8652 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008653 in->config.rate = config->sample_rate;
8654 in->sample_rate = config->sample_rate;
8655 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008656 //XXX needed for voice_extn_compress_voip_open_input_stream
8657 in->config.rate = config->sample_rate;
8658 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
Shalini Manjunathacd1de7d2019-08-23 15:13:46 +05308659 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008660 voice_extn_compress_voip_is_active(in->dev)) &&
8661 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8662 valid_rate && valid_ch) {
8663 voice_extn_compress_voip_open_input_stream(in);
8664 // update rate entries to match config from AF
8665 in->config.rate = config->sample_rate;
8666 in->sample_rate = config->sample_rate;
8667 } else {
8668 ALOGW("%s compress voip not active, use defaults", __func__);
8669 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008670 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008671 return 0;
8672}
8673
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008674static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008675 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008676 audio_devices_t devices,
8677 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008678 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308679 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008680 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008681 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008682{
8683 struct audio_device *adev = (struct audio_device *)dev;
8684 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008685 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008686 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008687 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308688 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008689 bool is_usb_dev = audio_is_usb_in_device(devices);
8690 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8691 devices,
8692 flags,
8693 source);
Andy Hung94320602018-10-29 18:31:12 -07008694 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8695 " sample_rate %u, channel_mask %#x, format %#x",
8696 __func__, flags, is_usb_dev, may_use_hifi_record,
8697 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308698
kunleizdff872d2018-08-20 14:40:33 +08008699 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008700 is_usb_dev = false;
8701 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8702 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8703 __func__, devices);
8704 }
8705
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008706 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008707
8708 if (!(is_usb_dev && may_use_hifi_record)) {
8709 if (config->sample_rate == 0)
8710 config->sample_rate = 48000;
8711 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8712 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8713 if (config->format == AUDIO_FORMAT_DEFAULT)
8714 config->format = AUDIO_FORMAT_PCM_16_BIT;
8715
8716 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8717
Aalique Grahame22e49102018-12-18 14:23:57 -08008718 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8719 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008720 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308721 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008722
Rahul Sharma99770982019-03-06 17:05:26 +05308723 pthread_mutex_lock(&adev->lock);
8724 if (in_get_stream(adev, handle) != NULL) {
8725 ALOGW("%s, input stream already opened", __func__);
8726 ret = -EEXIST;
8727 }
8728 pthread_mutex_unlock(&adev->lock);
8729 if (ret)
8730 return ret;
8731
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008732 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008733
8734 if (!in) {
8735 ALOGE("failed to allocate input stream");
8736 return -ENOMEM;
8737 }
8738
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308739 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308740 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8741 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008742 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008743 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008745 in->stream.common.get_sample_rate = in_get_sample_rate;
8746 in->stream.common.set_sample_rate = in_set_sample_rate;
8747 in->stream.common.get_buffer_size = in_get_buffer_size;
8748 in->stream.common.get_channels = in_get_channels;
8749 in->stream.common.get_format = in_get_format;
8750 in->stream.common.set_format = in_set_format;
8751 in->stream.common.standby = in_standby;
8752 in->stream.common.dump = in_dump;
8753 in->stream.common.set_parameters = in_set_parameters;
8754 in->stream.common.get_parameters = in_get_parameters;
8755 in->stream.common.add_audio_effect = in_add_audio_effect;
8756 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8757 in->stream.set_gain = in_set_gain;
8758 in->stream.read = in_read;
8759 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008760 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308761 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008762 in->stream.set_microphone_direction = in_set_microphone_direction;
8763 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008764 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008765
8766 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008767 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008768 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008769 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008770 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008771 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008772 in->bit_width = 16;
8773 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008774 in->direction = MIC_DIRECTION_UNSPECIFIED;
8775 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08008776 list_init(&in->aec_list);
8777 list_init(&in->ns_list);
Haynes Mathew George46740472017-10-27 18:40:12 -07008778
Andy Hung94320602018-10-29 18:31:12 -07008779 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008780 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8781 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8782 /* Force channel config requested to mono if incall
8783 record is being requested for only uplink/downlink */
8784 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8785 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8786 ret = -EINVAL;
8787 goto err_open;
8788 }
8789 }
8790
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008791 if (is_usb_dev && may_use_hifi_record) {
8792 /* HiFi record selects an appropriate format, channel, rate combo
8793 depending on sink capabilities*/
8794 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8795 &config->format,
8796 &in->supported_formats[0],
8797 MAX_SUPPORTED_FORMATS,
8798 &config->channel_mask,
8799 &in->supported_channel_masks[0],
8800 MAX_SUPPORTED_CHANNEL_MASKS,
8801 &config->sample_rate,
8802 &in->supported_sample_rates[0],
8803 MAX_SUPPORTED_SAMPLE_RATES);
8804 if (ret != 0) {
8805 ret = -EINVAL;
8806 goto err_open;
8807 }
8808 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008809 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308810 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308811 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8812 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8813 in->config.format = PCM_FORMAT_S32_LE;
8814 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308815 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8816 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8817 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8818 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8819 bool ret_error = false;
8820 in->bit_width = 24;
8821 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8822 from HAL is 24_packed and 8_24
8823 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8824 24_packed return error indicating supported format is 24_packed
8825 *> In case of any other source requesting 24 bit or float return error
8826 indicating format supported is 16 bit only.
8827
8828 on error flinger will retry with supported format passed
8829 */
8830 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8831 (source != AUDIO_SOURCE_CAMCORDER)) {
8832 config->format = AUDIO_FORMAT_PCM_16_BIT;
8833 if (config->sample_rate > 48000)
8834 config->sample_rate = 48000;
8835 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008836 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8837 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308838 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8839 ret_error = true;
8840 }
8841
8842 if (ret_error) {
8843 ret = -EINVAL;
8844 goto err_open;
8845 }
8846 }
8847
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008848 in->channel_mask = config->channel_mask;
8849 in->format = config->format;
8850
8851 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308852
8853 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8854 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8855 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8856 else {
8857 ret = -EINVAL;
8858 goto err_open;
8859 }
8860 }
8861
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008862 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
Deeraj Somanfa377bf2019-02-06 12:57:59 +05308863 (flags & AUDIO_INPUT_FLAG_TIMESTAMP) == 0 &&
8864 (flags & AUDIO_INPUT_FLAG_COMPRESS) == 0 &&
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008865 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8866 is_low_latency = true;
8867#if LOW_LATENCY_CAPTURE_USE_CASE
8868 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8869#endif
8870 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008871 if (!in->realtime) {
8872 in->config = pcm_config_audio_capture;
8873 frame_size = audio_stream_in_frame_size(&in->stream);
8874 buffer_size = get_input_buffer_size(config->sample_rate,
8875 config->format,
8876 channel_count,
8877 is_low_latency);
8878 in->config.period_size = buffer_size / frame_size;
8879 in->config.rate = config->sample_rate;
8880 in->af_period_multiplier = 1;
8881 } else {
8882 // period size is left untouched for rt mode playback
8883 in->config = pcm_config_audio_capture_rt;
8884 in->af_period_multiplier = af_period_multiplier;
8885 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008886 }
8887
8888 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8889 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8890 in->realtime = 0;
8891 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8892 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008893 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008894 in->stream.start = in_start;
8895 in->stream.stop = in_stop;
8896 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8897 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008898 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8899 } else if (in->realtime) {
8900 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008901 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008902 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008903 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008904 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8905 in->config = pcm_config_audio_capture;
8906 frame_size = audio_stream_in_frame_size(&in->stream);
8907 buffer_size = get_input_buffer_size(config->sample_rate,
8908 config->format,
8909 channel_count,
8910 false /*is_low_latency*/);
8911 in->config.period_size = buffer_size / frame_size;
8912 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008913 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008914 switch (config->format) {
8915 case AUDIO_FORMAT_PCM_32_BIT:
8916 in->bit_width = 32;
8917 break;
8918 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8919 case AUDIO_FORMAT_PCM_8_24_BIT:
8920 in->bit_width = 24;
8921 break;
8922 default:
8923 in->bit_width = 16;
8924 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008925 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308926 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008927 if (config->sample_rate == 0)
8928 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8929 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8930 config->sample_rate != 8000) {
8931 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8932 ret = -EINVAL;
8933 goto err_open;
8934 }
8935 if (config->format == AUDIO_FORMAT_DEFAULT)
8936 config->format = AUDIO_FORMAT_PCM_16_BIT;
8937 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8938 config->format = AUDIO_FORMAT_PCM_16_BIT;
8939 ret = -EINVAL;
8940 goto err_open;
8941 }
8942
8943 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8944 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008945 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008946 in->af_period_multiplier = 1;
8947 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8948 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8949 (config->sample_rate == 8000 ||
8950 config->sample_rate == 16000 ||
8951 config->sample_rate == 32000 ||
8952 config->sample_rate == 48000) &&
8953 channel_count == 1) {
8954 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8955 in->config = pcm_config_audio_capture;
8956 frame_size = audio_stream_in_frame_size(&in->stream);
8957 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8958 config->sample_rate,
8959 config->format,
8960 channel_count, false /*is_low_latency*/);
8961 in->config.period_size = buffer_size / frame_size;
8962 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8963 in->config.rate = config->sample_rate;
8964 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008965 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308966 int ret_val;
8967 pthread_mutex_lock(&adev->lock);
8968 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8969 in, config, &channel_mask_updated);
8970 pthread_mutex_unlock(&adev->lock);
8971
8972 if (!ret_val) {
8973 if (channel_mask_updated == true) {
8974 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8975 __func__, config->channel_mask);
8976 ret = -EINVAL;
8977 goto err_open;
8978 }
8979 ALOGD("%s: created multi-channel session succesfully",__func__);
8980 } else if (audio_extn_compr_cap_enabled() &&
8981 audio_extn_compr_cap_format_supported(config->format) &&
8982 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8983 audio_extn_compr_cap_init(in);
8984 } else if (audio_extn_cin_applicable_stream(in)) {
Deeraj Soman14230922019-01-30 16:39:30 +05308985 ret = audio_extn_cin_configure_input_stream(in, config);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308986 if (ret)
8987 goto err_open;
8988 } else {
8989 in->config = pcm_config_audio_capture;
8990 in->config.rate = config->sample_rate;
8991 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308992 in->format = config->format;
8993 frame_size = audio_stream_in_frame_size(&in->stream);
8994 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008995 config->format,
8996 channel_count,
8997 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008998 /* prevent division-by-zero */
8999 if (frame_size == 0) {
9000 ALOGE("%s: Error frame_size==0", __func__);
9001 ret = -EINVAL;
9002 goto err_open;
9003 }
9004
Revathi Uddarajud2634032017-12-07 14:42:34 +05309005 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08009006 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009007
Revathi Uddarajud2634032017-12-07 14:42:34 +05309008 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
9009 /* optionally use VOIP usecase depending on config(s) */
9010 ret = adev_update_voice_comm_input_stream(in, config);
9011 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009012
Revathi Uddarajud2634032017-12-07 14:42:34 +05309013 if (ret) {
9014 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
9015 goto err_open;
9016 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009017 }
Samyak Jainc37062f2019-04-25 18:41:06 +05309018 if (audio_extn_is_concurrent_capture_enabled()) {
9019 /* Acquire lock to avoid two concurrent use cases initialized to
9020 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08009021
Samyak Jainc37062f2019-04-25 18:41:06 +05309022 if (in->usecase == USECASE_AUDIO_RECORD) {
9023 pthread_mutex_lock(&adev->lock);
9024 if (!(adev->pcm_record_uc_state)) {
9025 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
9026 adev->pcm_record_uc_state = 1;
9027 pthread_mutex_unlock(&adev->lock);
9028 } else {
9029 pthread_mutex_unlock(&adev->lock);
9030 /* Assign compress record use case for second record */
9031 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
9032 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
9033 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
9034 if (audio_extn_cin_applicable_stream(in)) {
9035 in->sample_rate = config->sample_rate;
Deeraj Soman14230922019-01-30 16:39:30 +05309036 ret = audio_extn_cin_configure_input_stream(in, config);
Samyak Jainc37062f2019-04-25 18:41:06 +05309037 if (ret)
9038 goto err_open;
9039 }
9040 }
9041 }
kunleiz28c73e72019-03-27 17:24:04 +08009042 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009043 }
Ramjee Singh8b09cc12019-08-21 16:31:33 +05309044 if (audio_extn_ssr_get_stream() != in)
9045 in->config.channels = channel_count;
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009046
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07009047 in->sample_rate = in->config.rate;
9048
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309049 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
9050 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08009051 devices, flags, in->format,
9052 in->sample_rate, in->bit_width,
9053 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05309054 register_format(in->format, in->supported_formats);
9055 register_channel_mask(in->channel_mask, in->supported_channel_masks);
9056 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309057
Aalique Grahame22e49102018-12-18 14:23:57 -08009058 in->error_log = error_log_create(
9059 ERROR_LOG_ENTRIES,
9060 1000000000 /* aggregate consecutive identical errors within one second */);
9061
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009062 /* This stream could be for sound trigger lab,
9063 get sound trigger pcm if present */
9064 audio_extn_sound_trigger_check_and_get_session(in);
9065
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309066 lock_input_stream(in);
9067 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
9068 pthread_mutex_lock(&adev->lock);
9069 in->card_status = adev->card_status;
9070 pthread_mutex_unlock(&adev->lock);
9071 pthread_mutex_unlock(&in->lock);
9072
Aalique Grahame22e49102018-12-18 14:23:57 -08009073 stream_app_type_cfg_init(&in->app_type_cfg);
9074
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009075 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08009076
9077 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
9078 calloc(1, sizeof(streams_input_ctxt_t));
9079 if (in_ctxt == NULL) {
9080 ALOGE("%s fail to allocate input ctxt", __func__);
9081 ret = -ENOMEM;
9082 goto err_open;
9083 }
9084 in_ctxt->input = in;
9085
9086 pthread_mutex_lock(&adev->lock);
9087 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
9088 pthread_mutex_unlock(&adev->lock);
9089
Eric Laurent994a6932013-07-17 11:51:42 -07009090 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08009091 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009092
9093err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05309094 if (in->usecase == USECASE_AUDIO_RECORD) {
9095 pthread_mutex_lock(&adev->lock);
9096 adev->pcm_record_uc_state = 0;
9097 pthread_mutex_unlock(&adev->lock);
9098 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009099 free(in);
9100 *stream_in = NULL;
9101 return ret;
9102}
9103
9104static void adev_close_input_stream(struct audio_hw_device *dev,
9105 struct audio_stream_in *stream)
9106{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009107 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009108 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009109 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309110
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05309111 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009112
kunleiz70e57612018-12-28 17:50:23 +08009113 /* must deregister from sndmonitor first to prevent races
9114 * between the callback and close_stream
9115 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309116 audio_extn_snd_mon_unregister_listener(stream);
9117
kunleiz70e57612018-12-28 17:50:23 +08009118 /* Disable echo reference if there are no active input, hfp call
9119 * and sound trigger while closing input stream
9120 */
Eric Laurent637e2d42018-11-15 12:24:31 -08009121 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08009122 !audio_extn_hfp_is_active(adev) &&
9123 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08009124 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08009125 else
9126 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05309127
Pallavid7c7a272018-01-16 11:22:55 +05309128 if (in == NULL) {
9129 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
9130 return;
9131 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08009132 error_log_destroy(in->error_log);
9133 in->error_log = NULL;
9134
Pallavid7c7a272018-01-16 11:22:55 +05309135
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009136 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309137 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009138 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05309139 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08009140 if (ret != 0)
9141 ALOGE("%s: Compress voip input cannot be closed, error:%d",
9142 __func__, ret);
9143 } else
9144 in_standby(&stream->common);
9145
Revathi Uddarajud2634032017-12-07 14:42:34 +05309146 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05309147 if (in->usecase == USECASE_AUDIO_RECORD) {
9148 adev->pcm_record_uc_state = 0;
9149 }
9150
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07009151 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07009152 audio_extn_ssr_deinit();
9153 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009154
Garmond Leunge2433c32017-09-28 21:51:22 -07009155 if (audio_extn_ffv_get_stream() == in) {
9156 audio_extn_ffv_stream_deinit();
9157 }
9158
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309159 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07009160 audio_extn_compr_cap_format_supported(in->config.format))
9161 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05309162
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309163 if (audio_extn_cin_attached_usecase(in->usecase))
Manish Dewangan46e07982018-12-13 18:18:59 +05309164 audio_extn_cin_free_input_stream_resources(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009165
Mingming Yinfd7607b2016-01-22 12:48:44 -08009166 if (in->is_st_session) {
9167 ALOGV("%s: sound trigger pcm stop lab", __func__);
9168 audio_extn_sound_trigger_stop_lab(in);
9169 }
Derek Chenf939fb72018-11-13 13:34:41 -08009170 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
9171 if (in_ctxt != NULL) {
9172 list_remove(&in_ctxt->list);
9173 free(in_ctxt);
9174 } else {
9175 ALOGW("%s, input stream already closed", __func__);
9176 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009177 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05309178 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009179 return;
9180}
9181
Aalique Grahame22e49102018-12-18 14:23:57 -08009182/* verifies input and output devices and their capabilities.
9183 *
9184 * This verification is required when enabling extended bit-depth or
9185 * sampling rates, as not all qcom products support it.
9186 *
9187 * Suitable for calling only on initialization such as adev_open().
9188 * It fills the audio_device use_case_table[] array.
9189 *
9190 * Has a side-effect that it needs to configure audio routing / devices
9191 * in order to power up the devices and read the device parameters.
9192 * It does not acquire any hw device lock. Should restore the devices
9193 * back to "normal state" upon completion.
9194 */
9195static int adev_verify_devices(struct audio_device *adev)
9196{
9197 /* enumeration is a bit difficult because one really wants to pull
9198 * the use_case, device id, etc from the hidden pcm_device_table[].
9199 * In this case there are the following use cases and device ids.
9200 *
9201 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9202 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9203 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9204 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9205 * [USECASE_AUDIO_RECORD] = {0, 0},
9206 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9207 * [USECASE_VOICE_CALL] = {2, 2},
9208 *
9209 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9210 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9211 */
9212
9213 /* should be the usecases enabled in adev_open_input_stream() */
9214 static const int test_in_usecases[] = {
9215 USECASE_AUDIO_RECORD,
9216 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9217 };
9218 /* should be the usecases enabled in adev_open_output_stream()*/
9219 static const int test_out_usecases[] = {
9220 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9221 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9222 };
9223 static const usecase_type_t usecase_type_by_dir[] = {
9224 PCM_PLAYBACK,
9225 PCM_CAPTURE,
9226 };
9227 static const unsigned flags_by_dir[] = {
9228 PCM_OUT,
9229 PCM_IN,
9230 };
9231
9232 size_t i;
9233 unsigned dir;
9234 const unsigned card_id = adev->snd_card;
9235
9236 for (dir = 0; dir < 2; ++dir) {
9237 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9238 const unsigned flags_dir = flags_by_dir[dir];
9239 const size_t testsize =
9240 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9241 const int *testcases =
9242 dir ? test_in_usecases : test_out_usecases;
9243 const audio_devices_t audio_device =
9244 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9245
9246 for (i = 0; i < testsize; ++i) {
9247 const audio_usecase_t audio_usecase = testcases[i];
9248 int device_id;
9249 struct pcm_params **pparams;
9250 struct stream_out out;
9251 struct stream_in in;
9252 struct audio_usecase uc_info;
9253 int retval;
9254
9255 pparams = &adev->use_case_table[audio_usecase];
9256 pcm_params_free(*pparams); /* can accept null input */
9257 *pparams = NULL;
9258
9259 /* find the device ID for the use case (signed, for error) */
9260 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9261 if (device_id < 0)
9262 continue;
9263
9264 /* prepare structures for device probing */
9265 memset(&uc_info, 0, sizeof(uc_info));
9266 uc_info.id = audio_usecase;
9267 uc_info.type = usecase_type;
9268 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009269 memset(&in, 0, sizeof(in));
9270 in.device = audio_device;
9271 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9272 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009273 }
9274 memset(&out, 0, sizeof(out));
9275 out.devices = audio_device; /* only field needed in select_devices */
9276 uc_info.stream.out = &out;
9277 uc_info.devices = audio_device;
9278 uc_info.in_snd_device = SND_DEVICE_NONE;
9279 uc_info.out_snd_device = SND_DEVICE_NONE;
9280 list_add_tail(&adev->usecase_list, &uc_info.list);
9281
9282 /* select device - similar to start_(in/out)put_stream() */
9283 retval = select_devices(adev, audio_usecase);
9284 if (retval >= 0) {
9285 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9286#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009287 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009288 if (*pparams) {
9289 ALOGV("%s: (%s) card %d device %d", __func__,
9290 dir ? "input" : "output", card_id, device_id);
9291 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9292 } else {
9293 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9294 }
9295#endif
9296 }
9297
9298 /* deselect device - similar to stop_(in/out)put_stream() */
9299 /* 1. Get and set stream specific mixer controls */
9300 retval = disable_audio_route(adev, &uc_info);
9301 /* 2. Disable the rx device */
9302 retval = disable_snd_device(adev,
9303 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9304 list_remove(&uc_info.list);
9305 }
9306 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009307 return 0;
9308}
9309
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309310int adev_create_audio_patch(struct audio_hw_device *dev,
9311 unsigned int num_sources,
9312 const struct audio_port_config *sources,
9313 unsigned int num_sinks,
9314 const struct audio_port_config *sinks,
9315 audio_patch_handle_t *handle)
9316{
Derek Chenf939fb72018-11-13 13:34:41 -08009317 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309318
Derek Chenf939fb72018-11-13 13:34:41 -08009319 ret = audio_extn_hw_loopback_create_audio_patch(dev,
9320 num_sources,
9321 sources,
9322 num_sinks,
9323 sinks,
9324 handle);
9325 ret |= audio_extn_auto_hal_create_audio_patch(dev,
9326 num_sources,
9327 sources,
9328 num_sinks,
9329 sinks,
9330 handle);
9331 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309332}
9333
9334int adev_release_audio_patch(struct audio_hw_device *dev,
9335 audio_patch_handle_t handle)
9336{
Derek Chenf939fb72018-11-13 13:34:41 -08009337 int ret;
9338
9339 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
9340 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
9341 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309342}
9343
9344int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9345{
Derek Chenf13dd492018-11-13 14:53:51 -08009346 int ret = 0;
9347
9348 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9349 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9350 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309351}
9352
9353int adev_set_audio_port_config(struct audio_hw_device *dev,
9354 const struct audio_port_config *config)
9355{
Derek Chenf13dd492018-11-13 14:53:51 -08009356 int ret = 0;
9357
9358 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9359 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9360 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309361}
9362
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009363static int adev_dump(const audio_hw_device_t *device __unused,
9364 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009365{
9366 return 0;
9367}
9368
9369static int adev_close(hw_device_t *device)
9370{
Aalique Grahame22e49102018-12-18 14:23:57 -08009371 size_t i;
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309372 struct audio_device *adev_temp = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009373
Preetam Singh Ranawatacc64542019-06-24 15:11:28 +05309374 if (!adev_temp)
Kiran Kandi910e1862013-10-29 13:29:42 -07009375 return 0;
9376
9377 pthread_mutex_lock(&adev_init_lock);
9378
9379 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309380 if (audio_extn_spkr_prot_is_enabled())
9381 audio_extn_spkr_prot_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309382 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009383 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009384 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009385 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009386 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309387 audio_extn_utils_release_streams_cfg_lists(
9388 &adev->streams_output_cfg_list,
9389 &adev->streams_input_cfg_list);
Sidipotu Ashokd2f10ba2019-05-06 15:41:56 +05309390 if (audio_extn_qap_is_enabled())
9391 audio_extn_qap_deinit();
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309392 if (audio_extn_qaf_is_enabled())
9393 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009394 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009395 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009396 free(adev->snd_dev_ref_cnt);
9397 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009398 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9399 pcm_params_free(adev->use_case_table[i]);
9400 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009401 if (adev->adm_deinit)
9402 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309403 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009404 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309405 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309406 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009407 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309408 if (adev->device_cfg_params) {
9409 free(adev->device_cfg_params);
9410 adev->device_cfg_params = NULL;
9411 }
Derek Chend2530072014-11-24 12:39:14 -08009412 if(adev->ext_hw_plugin)
9413 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009414 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009415 free(device);
9416 adev = NULL;
9417 }
9418 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309419 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009420 return 0;
9421}
9422
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009423/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9424 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9425 * just that it _might_ work.
9426 */
9427static int period_size_is_plausible_for_low_latency(int period_size)
9428{
9429 switch (period_size) {
9430 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009431 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009432 case 240:
9433 case 320:
9434 case 480:
9435 return 1;
9436 default:
9437 return 0;
9438 }
9439}
9440
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309441static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9442{
9443 bool is_snd_card_status = false;
9444 bool is_ext_device_status = false;
9445 char value[32];
9446 int card = -1;
9447 card_status_t status;
9448
9449 if (cookie != adev || !parms)
9450 return;
9451
9452 if (!parse_snd_card_status(parms, &card, &status)) {
9453 is_snd_card_status = true;
9454 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9455 is_ext_device_status = true;
9456 } else {
9457 // not a valid event
9458 return;
9459 }
9460
9461 pthread_mutex_lock(&adev->lock);
9462 if (card == adev->snd_card || is_ext_device_status) {
9463 if (is_snd_card_status && adev->card_status != status) {
9464 adev->card_status = status;
9465 platform_snd_card_update(adev->platform, status);
9466 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -08009467 audio_extn_auto_hal_set_parameters(adev, parms);
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;
Aalique Grahame22e49102018-12-18 14:23:57 -08009815 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9816 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009817 trial = atoi(value);
9818 if (period_size_is_plausible_for_low_latency(trial)) {
9819 pcm_config_low_latency.period_size = trial;
9820 pcm_config_low_latency.start_threshold = trial / 4;
9821 pcm_config_low_latency.avail_min = trial / 4;
9822 configured_low_latency_capture_period_size = trial;
9823 }
9824 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009825 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9826 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009827 trial = atoi(value);
9828 if (period_size_is_plausible_for_low_latency(trial)) {
9829 configured_low_latency_capture_period_size = trial;
9830 }
9831 }
9832
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009833 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9834
Eric Laurent4b084132018-10-19 17:33:43 -07009835 adev->camera_orientation = CAMERA_DEFAULT;
9836
Aalique Grahame22e49102018-12-18 14:23:57 -08009837 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9838 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009839 af_period_multiplier = atoi(value);
9840 if (af_period_multiplier < 0)
9841 af_period_multiplier = 2;
9842 else if (af_period_multiplier > 4)
9843 af_period_multiplier = 4;
9844
9845 ALOGV("new period_multiplier = %d", af_period_multiplier);
9846 }
9847
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009848 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009849
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009850 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009851 pthread_mutex_unlock(&adev_init_lock);
9852
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009853 if (adev->adm_init)
9854 adev->adm_data = adev->adm_init();
9855
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309856 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309857 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009858 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309859
9860 audio_extn_snd_mon_init();
9861 pthread_mutex_lock(&adev->lock);
9862 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9863 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009864 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9865 /*
9866 * if the battery state callback happens before charging can be queried,
9867 * it will be guarded with the adev->lock held in the cb function and so
9868 * the callback value will reflect the latest state
9869 */
9870 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309871 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009872 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009873 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009874 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309875 /* Allocate memory for Device config params */
9876 adev->device_cfg_params = (struct audio_device_config_param*)
9877 calloc(platform_get_max_codec_backend(),
9878 sizeof(struct audio_device_config_param));
9879 if (adev->device_cfg_params == NULL)
9880 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309881
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309882 /*
9883 * Check if new PSPD matrix mixer control is supported. If not
9884 * supported, then set flag so that old mixer ctrl is sent while
9885 * sending pspd coefficients on older kernel version. Query mixer
9886 * control for default pcm id and channel value one.
9887 */
9888 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9889 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9890
9891 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9892 if (!ctl) {
9893 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9894 __func__, mixer_ctl_name);
9895 adev->use_old_pspd_mix_ctrl = true;
9896 }
9897
Eric Laurent994a6932013-07-17 11:51:42 -07009898 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009899 return 0;
9900}
9901
9902static struct hw_module_methods_t hal_module_methods = {
9903 .open = adev_open,
9904};
9905
9906struct audio_module HAL_MODULE_INFO_SYM = {
9907 .common = {
9908 .tag = HARDWARE_MODULE_TAG,
9909 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9910 .hal_api_version = HARDWARE_HAL_API_VERSION,
9911 .id = AUDIO_HARDWARE_MODULE_ID,
9912 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009913 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009914 .methods = &hal_module_methods,
9915 },
9916};