blob: 3390527c7d9ec5c0f2adc9cfb42c34b68294944c [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080072#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070096#define INVALID_OUT_VOLUME -1
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097
Aalique Grahame22e49102018-12-18 14:23:57 -080098#define RECORD_GAIN_MIN 0.0f
99#define RECORD_GAIN_MAX 1.0f
100#define RECORD_VOLUME_CTL_MAX 0x2000
101
102/* treat as unsigned Q1.13 */
103#define APP_TYPE_GAIN_DEFAULT 0x2000
104
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700105#define PROXY_OPEN_RETRY_COUNT 100
106#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800107
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800108#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
109 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
110 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
111#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
112 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800113
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700114#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700115#define DEFAULT_VOIP_BUF_DURATION_MS 20
116#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
117#define DEFAULT_VOIP_SAMP_RATE 48000
118
119#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
120
121struct pcm_config default_pcm_config_voip_copp = {
122 .channels = 1,
123 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
124 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
125 .period_count = 2,
126 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800127 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
128 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700129};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700130
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700131#define MIN_CHANNEL_COUNT 1
132#define DEFAULT_CHANNEL_COUNT 2
133#define MAX_HIFI_CHANNEL_COUNT 8
134
Aalique Grahame22e49102018-12-18 14:23:57 -0800135#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
136#define MAX_CHANNEL_COUNT 1
137#else
138#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
139#define XSTR(x) STR(x)
140#define STR(x) #x
141#endif
142
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700143static unsigned int configured_low_latency_capture_period_size =
144 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
145
Haynes Mathew George16081042017-05-31 17:16:49 -0700146#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
147#define MMAP_PERIOD_COUNT_MIN 32
148#define MMAP_PERIOD_COUNT_MAX 512
149#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
150
Aalique Grahame22e49102018-12-18 14:23:57 -0800151/* This constant enables extended precision handling.
152 * TODO The flag is off until more testing is done.
153 */
154static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700155extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800156
Eric Laurentb23d5282013-05-14 15:27:20 -0700157struct pcm_config pcm_config_deep_buffer = {
158 .channels = 2,
159 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
160 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
161 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
162 .format = PCM_FORMAT_S16_LE,
163 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
164 .stop_threshold = INT_MAX,
165 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166};
167
168struct pcm_config pcm_config_low_latency = {
169 .channels = 2,
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
171 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
172 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
173 .format = PCM_FORMAT_S16_LE,
174 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
175 .stop_threshold = INT_MAX,
176 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177};
178
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800179struct pcm_config pcm_config_haptics_audio = {
180 .channels = 1,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
183 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
186 .stop_threshold = INT_MAX,
187 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188};
189
190struct pcm_config pcm_config_haptics = {
191 .channels = 1,
192 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
193 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
194 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
195 .format = PCM_FORMAT_S16_LE,
196 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
197 .stop_threshold = INT_MAX,
198 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
199};
200
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700201static int af_period_multiplier = 4;
202struct pcm_config pcm_config_rt = {
203 .channels = 2,
204 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
205 .period_size = ULL_PERIOD_SIZE, //1 ms
206 .period_count = 512, //=> buffer size is 512ms
207 .format = PCM_FORMAT_S16_LE,
208 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
209 .stop_threshold = INT_MAX,
210 .silence_threshold = 0,
211 .silence_size = 0,
212 .avail_min = ULL_PERIOD_SIZE, //1 ms
213};
214
Eric Laurentb23d5282013-05-14 15:27:20 -0700215struct pcm_config pcm_config_hdmi_multi = {
216 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
217 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
218 .period_size = HDMI_MULTI_PERIOD_SIZE,
219 .period_count = HDMI_MULTI_PERIOD_COUNT,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = 0,
222 .stop_threshold = INT_MAX,
223 .avail_min = 0,
224};
225
Haynes Mathew George16081042017-05-31 17:16:49 -0700226struct pcm_config pcm_config_mmap_playback = {
227 .channels = 2,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = MMAP_PERIOD_SIZE*8,
233 .stop_threshold = INT32_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700239struct pcm_config pcm_config_hifi = {
240 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
241 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
242 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
243 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
244 .format = PCM_FORMAT_S24_3LE,
245 .start_threshold = 0,
246 .stop_threshold = INT_MAX,
247 .avail_min = 0,
248};
249
Eric Laurentb23d5282013-05-14 15:27:20 -0700250struct pcm_config pcm_config_audio_capture = {
251 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700252 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
253 .format = PCM_FORMAT_S16_LE,
254};
255
Haynes Mathew George16081042017-05-31 17:16:49 -0700256struct pcm_config pcm_config_mmap_capture = {
257 .channels = 2,
258 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
259 .period_size = MMAP_PERIOD_SIZE,
260 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
261 .format = PCM_FORMAT_S16_LE,
262 .start_threshold = 0,
263 .stop_threshold = INT_MAX,
264 .silence_threshold = 0,
265 .silence_size = 0,
266 .avail_min = MMAP_PERIOD_SIZE, //1 ms
267};
268
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700269#define AFE_PROXY_CHANNEL_COUNT 2
270#define AFE_PROXY_SAMPLING_RATE 48000
271
272#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
273#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
274
275struct pcm_config pcm_config_afe_proxy_playback = {
276 .channels = AFE_PROXY_CHANNEL_COUNT,
277 .rate = AFE_PROXY_SAMPLING_RATE,
278 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
279 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
280 .format = PCM_FORMAT_S16_LE,
281 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
282 .stop_threshold = INT_MAX,
283 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284};
285
286#define AFE_PROXY_RECORD_PERIOD_SIZE 768
287#define AFE_PROXY_RECORD_PERIOD_COUNT 4
288
Aalique Grahame22e49102018-12-18 14:23:57 -0800289struct pcm_config pcm_config_audio_capture_rt = {
290 .channels = 2,
291 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
292 .period_size = ULL_PERIOD_SIZE,
293 .period_count = 512,
294 .format = PCM_FORMAT_S16_LE,
295 .start_threshold = 0,
296 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
297 .silence_threshold = 0,
298 .silence_size = 0,
299 .avail_min = ULL_PERIOD_SIZE, //1 ms
300};
301
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700302struct pcm_config pcm_config_afe_proxy_record = {
303 .channels = AFE_PROXY_CHANNEL_COUNT,
304 .rate = AFE_PROXY_SAMPLING_RATE,
305 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
306 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
307 .format = PCM_FORMAT_S16_LE,
308 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
309 .stop_threshold = INT_MAX,
310 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
311};
312
Ashish Jainf1eaa582016-05-23 20:54:24 +0530313#define AUDIO_MAX_PCM_FORMATS 7
314
315const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
316 [AUDIO_FORMAT_DEFAULT] = 0,
317 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
318 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
319 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
320 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
321 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
322 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
323};
324
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800325const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700326 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
327 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800328 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700329 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
330 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700331 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700332 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700333 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
334 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700341 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
342 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700343 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800344 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700345
Eric Laurentb23d5282013-05-14 15:27:20 -0700346 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700347 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530348 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
349 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
350 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530351 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
352 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700353 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700354 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700355 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700356 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700357
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800358 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800359 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700360 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700361
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700362 [USECASE_VOICE2_CALL] = "voice2-call",
363 [USECASE_VOLTE_CALL] = "volte-call",
364 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800365 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800366 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
367 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800368 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700369 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
370 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
371 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800372 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
373 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
374 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
375
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700376 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
377 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700378 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
379 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700380
381 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
382 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530383 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700384
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530385 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530386 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
387 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700388
389 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
390 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530391 /* For Interactive Audio Streams */
392 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700400
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800401 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
402
Derek Chenf6318be2017-06-12 17:16:24 -0400403 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
404
405 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
406 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
407 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
408 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700409};
410
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700411static const audio_usecase_t offload_usecases[] = {
412 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700413 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
414 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
415 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
416 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
417 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
418 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
419 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700421};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800422
Varun Balaraje49253e2017-07-06 19:48:56 +0530423static const audio_usecase_t interactive_usecases[] = {
424 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
426 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
427 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
428 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
429 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
432};
433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800434#define STRING_TO_ENUM(string) { #string, string }
435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436struct string_to_enum {
437 const char *name;
438 uint32_t value;
439};
440
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700441static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800442 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
444 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
445 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700446 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800447 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700450 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
451 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
452 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
453 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
455 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
456 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
457 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
458 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800461};
462
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700463static const struct string_to_enum formats_name_to_enum_table[] = {
464 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
465 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
466 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700467 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
468 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
469 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700470 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800471 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
472 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700473 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800474};
475
476//list of all supported sample rates by HDMI specification.
477static const int out_hdmi_sample_rates[] = {
478 32000, 44100, 48000, 88200, 96000, 176400, 192000,
479};
480
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700481static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800482 STRING_TO_ENUM(32000),
483 STRING_TO_ENUM(44100),
484 STRING_TO_ENUM(48000),
485 STRING_TO_ENUM(88200),
486 STRING_TO_ENUM(96000),
487 STRING_TO_ENUM(176400),
488 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700489};
490
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700491static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700492static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700493static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700494//cache last MBDRC cal step level
495static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700496
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530497static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
498static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700499static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800500static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530501static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530502
Vatsal Buchac09ae062018-11-14 13:25:08 +0530503#ifdef AUDIO_FEATURE_ENABLED_GCOV
504extern void __gcov_flush();
505static void enable_gcov()
506{
507 __gcov_flush();
508}
509#else
510static void enable_gcov()
511{
512}
513#endif
514
justinweng20fb6d82019-02-21 18:49:00 -0700515static int in_set_microphone_direction(const struct audio_stream_in *stream,
516 audio_microphone_direction_t dir);
517static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
518
519
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700520static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
521 int flags __unused)
522{
523 int dir = 0;
524 switch (uc_id) {
525 case USECASE_AUDIO_RECORD_LOW_LATENCY:
526 dir = 1;
527 case USECASE_AUDIO_PLAYBACK_ULL:
528 break;
529 default:
530 return false;
531 }
532
533 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
534 PCM_PLAYBACK : PCM_CAPTURE);
535 if (adev->adm_is_noirq_avail)
536 return adev->adm_is_noirq_avail(adev->adm_data,
537 adev->snd_card, dev_id, dir);
538 return false;
539}
540
541static void register_out_stream(struct stream_out *out)
542{
543 struct audio_device *adev = out->dev;
544 if (is_offload_usecase(out->usecase) ||
545 !adev->adm_register_output_stream)
546 return;
547
548 // register stream first for backward compatibility
549 adev->adm_register_output_stream(adev->adm_data,
550 out->handle,
551 out->flags);
552
553 if (!adev->adm_set_config)
554 return;
555
556 if (out->realtime)
557 adev->adm_set_config(adev->adm_data,
558 out->handle,
559 out->pcm, &out->config);
560}
561
562static void register_in_stream(struct stream_in *in)
563{
564 struct audio_device *adev = in->dev;
565 if (!adev->adm_register_input_stream)
566 return;
567
568 adev->adm_register_input_stream(adev->adm_data,
569 in->capture_handle,
570 in->flags);
571
572 if (!adev->adm_set_config)
573 return;
574
575 if (in->realtime)
576 adev->adm_set_config(adev->adm_data,
577 in->capture_handle,
578 in->pcm,
579 &in->config);
580}
581
582static void request_out_focus(struct stream_out *out, long ns)
583{
584 struct audio_device *adev = out->dev;
585
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700586 if (adev->adm_request_focus_v2)
587 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
588 else if (adev->adm_request_focus)
589 adev->adm_request_focus(adev->adm_data, out->handle);
590}
591
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700592static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700593{
594 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700595 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700596
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700597 if (adev->adm_request_focus_v2_1)
598 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
599 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700600 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
601 else if (adev->adm_request_focus)
602 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700603
604 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700605}
606
607static void release_out_focus(struct stream_out *out)
608{
609 struct audio_device *adev = out->dev;
610
611 if (adev->adm_abandon_focus)
612 adev->adm_abandon_focus(adev->adm_data, out->handle);
613}
614
615static void release_in_focus(struct stream_in *in)
616{
617 struct audio_device *adev = in->dev;
618 if (adev->adm_abandon_focus)
619 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
620}
621
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530622static int parse_snd_card_status(struct str_parms *parms, int *card,
623 card_status_t *status)
624{
625 char value[32]={0};
626 char state[32]={0};
627
628 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
629 if (ret < 0)
630 return -1;
631
632 // sscanf should be okay as value is of max length 32.
633 // same as sizeof state.
634 if (sscanf(value, "%d,%s", card, state) < 2)
635 return -1;
636
637 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
638 CARD_STATUS_OFFLINE;
639 return 0;
640}
641
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700642static inline void adjust_frames_for_device_delay(struct stream_out *out,
643 uint32_t *dsp_frames) {
644 // Adjustment accounts for A2dp encoder latency with offload usecases
645 // Note: Encoder latency is returned in ms.
646 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
647 unsigned long offset =
648 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
649 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
650 }
651}
652
vivek mehtaa76401a2015-04-24 14:12:15 -0700653__attribute__ ((visibility ("default")))
654bool audio_hw_send_gain_dep_calibration(int level) {
655 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700656 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700657
658 pthread_mutex_lock(&adev_init_lock);
659
660 if (adev != NULL && adev->platform != NULL) {
661 pthread_mutex_lock(&adev->lock);
662 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700663
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530664 // cache level info for any of the use case which
665 // was not started.
666 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700667
vivek mehtaa76401a2015-04-24 14:12:15 -0700668 pthread_mutex_unlock(&adev->lock);
669 } else {
670 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
671 }
672
673 pthread_mutex_unlock(&adev_init_lock);
674
675 return ret_val;
676}
677
Ashish Jain5106d362016-05-11 19:23:33 +0530678static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
679{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800680 bool gapless_enabled = false;
681 const char *mixer_ctl_name = "Compress Gapless Playback";
682 struct mixer_ctl *ctl;
683
684 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700685 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530686
687 /*Disable gapless if its AV playback*/
688 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800689
690 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
691 if (!ctl) {
692 ALOGE("%s: Could not get ctl for mixer cmd - %s",
693 __func__, mixer_ctl_name);
694 return -EINVAL;
695 }
696
697 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
698 ALOGE("%s: Could not set gapless mode %d",
699 __func__, gapless_enabled);
700 return -EINVAL;
701 }
702 return 0;
703}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700704
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700705__attribute__ ((visibility ("default")))
706int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
707 int table_size) {
708 int ret_val = 0;
709 ALOGV("%s: enter ... ", __func__);
710
711 pthread_mutex_lock(&adev_init_lock);
712 if (adev == NULL) {
713 ALOGW("%s: adev is NULL .... ", __func__);
714 goto done;
715 }
716
717 pthread_mutex_lock(&adev->lock);
718 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
719 pthread_mutex_unlock(&adev->lock);
720done:
721 pthread_mutex_unlock(&adev_init_lock);
722 ALOGV("%s: exit ... ", __func__);
723 return ret_val;
724}
725
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800726bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800727{
728 bool ret = false;
729 ALOGV("%s: enter ...", __func__);
730
731 pthread_mutex_lock(&adev_init_lock);
732
733 if (adev != NULL && adev->platform != NULL) {
734 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800735 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800736 pthread_mutex_unlock(&adev->lock);
737 }
738
739 pthread_mutex_unlock(&adev_init_lock);
740
741 ALOGV("%s: exit with ret %d", __func__, ret);
742 return ret;
743}
Aalique Grahame22e49102018-12-18 14:23:57 -0800744
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700745static bool is_supported_format(audio_format_t format)
746{
Eric Laurent86e17132013-09-12 17:49:30 -0700747 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530748 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530749 format == AUDIO_FORMAT_AAC_LC ||
750 format == AUDIO_FORMAT_AAC_HE_V1 ||
751 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530752 format == AUDIO_FORMAT_AAC_ADTS_LC ||
753 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
754 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530755 format == AUDIO_FORMAT_AAC_LATM_LC ||
756 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
757 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530758 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
759 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530760 format == AUDIO_FORMAT_PCM_FLOAT ||
761 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700762 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530763 format == AUDIO_FORMAT_AC3 ||
764 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700765 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530766 format == AUDIO_FORMAT_DTS ||
767 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800768 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530769 format == AUDIO_FORMAT_ALAC ||
770 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530771 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530772 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800773 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530774 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700775 format == AUDIO_FORMAT_APTX ||
776 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800777 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700778
779 return false;
780}
781
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700782static inline bool is_mmap_usecase(audio_usecase_t uc_id)
783{
784 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
785 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
786}
787
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700788static inline bool is_valid_volume(float left, float right)
789{
790 return ((left >= 0.0f && right >= 0.0f) ? true : false);
791}
792
Avinash Vaish71a8b972014-07-24 15:36:33 +0530793static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
794 struct audio_usecase *uc_info)
795{
796 struct listnode *node;
797 struct audio_usecase *usecase;
798
799 if (uc_info == NULL)
800 return -EINVAL;
801
802 /* Re-route all voice usecases on the shared backend other than the
803 specified usecase to new snd devices */
804 list_for_each(node, &adev->usecase_list) {
805 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800806 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530807 enable_audio_route(adev, usecase);
808 }
809 return 0;
810}
811
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530812static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530813{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530814 ALOGV("%s", __func__);
815 audio_route_apply_and_update_path(adev->audio_route,
816 "asrc-mode");
817 adev->asrc_mode_enabled = true;
818}
819
820static void disable_asrc_mode(struct audio_device *adev)
821{
822 ALOGV("%s", __func__);
823 audio_route_reset_and_update_path(adev->audio_route,
824 "asrc-mode");
825 adev->asrc_mode_enabled = false;
826}
827
828/*
829 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
830 * 44.1 or Native DSD backends are enabled for any of current use case.
831 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
832 * - Disable current mix path use case(Headphone backend) and re-enable it with
833 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
834 * e.g. Naitve DSD or Headphone 44.1 -> + 48
835 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530836static void check_and_set_asrc_mode(struct audio_device *adev,
837 struct audio_usecase *uc_info,
838 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530839{
840 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530841 int i, num_new_devices = 0;
842 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
843 /*
844 *Split snd device for new combo use case
845 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
846 */
847 if (platform_split_snd_device(adev->platform,
848 snd_device,
849 &num_new_devices,
850 split_new_snd_devices) == 0) {
851 for (i = 0; i < num_new_devices; i++)
852 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
853 } else {
854 int new_backend_idx = platform_get_backend_index(snd_device);
855 if (((new_backend_idx == HEADPHONE_BACKEND) ||
856 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
857 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
858 !adev->asrc_mode_enabled) {
859 struct listnode *node = NULL;
860 struct audio_usecase *uc = NULL;
861 struct stream_out *curr_out = NULL;
862 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
863 int i, num_devices, ret = 0;
864 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530865
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530866 list_for_each(node, &adev->usecase_list) {
867 uc = node_to_item(node, struct audio_usecase, list);
868 curr_out = (struct stream_out*) uc->stream.out;
869 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
870 /*
871 *Split snd device for existing combo use case
872 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
873 */
874 ret = platform_split_snd_device(adev->platform,
875 uc->out_snd_device,
876 &num_devices,
877 split_snd_devices);
878 if (ret < 0 || num_devices == 0) {
879 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
880 split_snd_devices[0] = uc->out_snd_device;
881 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800882 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530883 for (i = 0; i < num_devices; i++) {
884 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
885 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
886 if((new_backend_idx == HEADPHONE_BACKEND) &&
887 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
888 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
889 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
890 __func__);
891 enable_asrc_mode(adev);
892 break;
893 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
894 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
895 (usecase_backend_idx == HEADPHONE_BACKEND)) {
896 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
897 __func__);
898 disable_audio_route(adev, uc);
899 disable_snd_device(adev, uc->out_snd_device);
900 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
901 if (new_backend_idx == DSD_NATIVE_BACKEND)
902 audio_route_apply_and_update_path(adev->audio_route,
903 "hph-true-highquality-mode");
904 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
905 (curr_out->bit_width >= 24))
906 audio_route_apply_and_update_path(adev->audio_route,
907 "hph-highquality-mode");
908 enable_asrc_mode(adev);
909 enable_snd_device(adev, uc->out_snd_device);
910 enable_audio_route(adev, uc);
911 break;
912 }
913 }
914 // reset split devices count
915 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800916 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530917 if (adev->asrc_mode_enabled)
918 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530919 }
920 }
921 }
922}
923
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700924static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
925 struct audio_effect_config effect_config,
926 unsigned int param_value)
927{
928 char mixer_ctl_name[] = "Audio Effect";
929 struct mixer_ctl *ctl;
930 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800931 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700932
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700933 if (in == NULL) {
934 ALOGE("%s: active input stream is NULL", __func__);
935 return -EINVAL;
936 }
937
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700938 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
939 if (!ctl) {
940 ALOGE("%s: Could not get mixer ctl - %s",
941 __func__, mixer_ctl_name);
942 return -EINVAL;
943 }
944
945 set_values[0] = 1; //0:Rx 1:Tx
946 set_values[1] = in->app_type_cfg.app_type;
947 set_values[2] = (long)effect_config.module_id;
948 set_values[3] = (long)effect_config.instance_id;
949 set_values[4] = (long)effect_config.param_id;
950 set_values[5] = param_value;
951
952 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
953
954 return 0;
955
956}
957
958static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
959 int effect_type, unsigned int *param_value)
960{
961 int ret = 0;
962 struct audio_effect_config other_effect_config;
963 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800964 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700965
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700966 if (in == NULL) {
967 ALOGE("%s: active input stream is NULL", __func__);
968 return -EINVAL;
969 }
970
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700971 usecase = get_usecase_from_list(adev, in->usecase);
972 if (!usecase)
973 return -EINVAL;
974
975 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
976 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
977 if (ret < 0) {
978 ALOGE("%s Failed to get effect params %d", __func__, ret);
979 return ret;
980 }
981
982 if (module_id == other_effect_config.module_id) {
983 //Same module id for AEC/NS. Values need to be combined
984 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
985 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
986 *param_value |= other_effect_config.param_value;
987 }
988 }
989
990 return ret;
991}
992
993static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +0530994{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700995 struct audio_effect_config effect_config;
996 struct audio_usecase *usecase = NULL;
997 int ret = 0;
998 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -0800999 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001000
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001001 if(!voice_extn_is_dynamic_ecns_enabled())
1002 return ENOSYS;
1003
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001004 if (!in) {
1005 ALOGE("%s: Invalid input stream", __func__);
1006 return -EINVAL;
1007 }
1008
1009 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1010
1011 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001012 if (usecase == NULL) {
1013 ALOGE("%s: Could not find the usecase (%d) in the list",
1014 __func__, in->usecase);
1015 return -EINVAL;
1016 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001017
1018 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1019 if (ret < 0) {
1020 ALOGE("%s Failed to get module id %d", __func__, ret);
1021 return ret;
1022 }
1023 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1024 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1025
1026 if(enable)
1027 param_value = effect_config.param_value;
1028
1029 /*Special handling for AEC & NS effects Param values need to be
1030 updated if module ids are same*/
1031
1032 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1033 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1034 if (ret < 0)
1035 return ret;
1036 }
1037
1038 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1039
1040 return ret;
1041}
1042
1043static void check_and_enable_effect(struct audio_device *adev)
1044{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001045 if(!voice_extn_is_dynamic_ecns_enabled())
1046 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001047
Eric Laurent637e2d42018-11-15 12:24:31 -08001048 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001049
Eric Laurent637e2d42018-11-15 12:24:31 -08001050 if (in != NULL && !in->standby) {
1051 if (in->enable_aec)
1052 enable_disable_effect(adev, EFFECT_AEC, true);
1053
1054 if (in->enable_ns &&
1055 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1056 enable_disable_effect(adev, EFFECT_NS, true);
1057 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001058 }
1059}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001060
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001061int pcm_ioctl(struct pcm *pcm, int request, ...)
1062{
1063 va_list ap;
1064 void * arg;
1065 int pcm_fd = *(int*)pcm;
1066
1067 va_start(ap, request);
1068 arg = va_arg(ap, void *);
1069 va_end(ap);
1070
1071 return ioctl(pcm_fd, request, arg);
1072}
1073
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001074int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001075 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001076{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001077 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001078 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301079 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301080 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001081
1082 if (usecase == NULL)
1083 return -EINVAL;
1084
1085 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1086
Surendar Karka93cd25a2018-08-28 14:21:37 +05301087 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001088 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001089 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001090 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001091
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001092#ifdef DS1_DOLBY_DAP_ENABLED
1093 audio_extn_dolby_set_dmid(adev);
1094 audio_extn_dolby_set_endpoint(adev);
1095#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001096 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001097 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301098 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001099 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001100 if (audio_extn_is_maxx_audio_enabled())
1101 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301102 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301103 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1104 out = usecase->stream.out;
1105 if (out && out->compr)
1106 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1107 }
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301108 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301109
Andy Hung756ecc12018-10-19 17:47:12 -07001110 // we shouldn't truncate mixer_path
1111 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1112 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1113 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001114 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001115 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301116 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1117 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1118 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1119 if (parms) {
1120 audio_extn_fm_set_parameters(adev, parms);
1121 str_parms_destroy(parms);
1122 }
1123 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001124 ALOGV("%s: exit", __func__);
1125 return 0;
1126}
1127
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001128int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001129 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001130{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001131 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001132 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001133
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301134 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001135 return -EINVAL;
1136
1137 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301138 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001139 snd_device = usecase->in_snd_device;
1140 else
1141 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001142 // we shouldn't truncate mixer_path
1143 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1144 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1145 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001146 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001147 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001148 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001149 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301150 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301151 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001152 if ((usecase->type == PCM_PLAYBACK) &&
1153 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301154 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001155 ALOGV("%s: exit", __func__);
1156 return 0;
1157}
1158
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001159int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001160 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001161{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301162 int i, num_devices = 0;
1163 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001164 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1165
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001166 if (snd_device < SND_DEVICE_MIN ||
1167 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001168 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001169 return -EINVAL;
1170 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001171
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001172 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001173 ALOGE("%s: Invalid sound device returned", __func__);
1174 return -EINVAL;
1175 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001176
1177 adev->snd_dev_ref_cnt[snd_device]++;
1178
1179 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1180 (platform_split_snd_device(adev->platform,
1181 snd_device,
1182 &num_devices,
1183 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001184 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001185 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001186 return 0;
1187 }
1188
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001189 if (audio_extn_spkr_prot_is_enabled())
1190 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001191
Aalique Grahame22e49102018-12-18 14:23:57 -08001192 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1193
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001194 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1195 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001196 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1197 goto err;
1198 }
1199 audio_extn_dev_arbi_acquire(snd_device);
1200 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001201 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001202 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001203 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001204 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001205 } else if (platform_split_snd_device(adev->platform,
1206 snd_device,
1207 &num_devices,
1208 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301209 for (i = 0; i < num_devices; i++) {
1210 enable_snd_device(adev, new_snd_devices[i]);
1211 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001212 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001213 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001214 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301215
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301216
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001217 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1218 (audio_extn_a2dp_start_playback() < 0)) {
1219 ALOGE(" fail to configure A2dp Source control path ");
1220 goto err;
1221 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001222
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001223 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1224 (audio_extn_a2dp_start_capture() < 0)) {
1225 ALOGE(" fail to configure A2dp Sink control path ");
1226 goto err;
1227 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301228
Zhou Song12c29502019-03-16 10:37:18 +08001229 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1230 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1231 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1232 (audio_extn_sco_start_configuration() < 0)) {
1233 ALOGE(" fail to configure sco control path ");
1234 goto err;
1235 }
1236
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001237 /* due to the possibility of calibration overwrite between listen
1238 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001239 audio_extn_sound_trigger_update_device_status(snd_device,
1240 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301241 audio_extn_listen_update_device_status(snd_device,
1242 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001243 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001244 audio_extn_sound_trigger_update_device_status(snd_device,
1245 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301246 audio_extn_listen_update_device_status(snd_device,
1247 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001248 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001249 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001250 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001251 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301252
1253 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1254 !adev->native_playback_enabled &&
1255 audio_is_true_native_stream_active(adev)) {
1256 ALOGD("%s: %d: napb: enabling native mode in hardware",
1257 __func__, __LINE__);
1258 audio_route_apply_and_update_path(adev->audio_route,
1259 "true-native-mode");
1260 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301261 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301262 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1263 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001264 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001265 ALOGD("%s: init ec ref loopback", __func__);
1266 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1267 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001269 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001270err:
1271 adev->snd_dev_ref_cnt[snd_device]--;
1272 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001273}
1274
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001275int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001276 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001277{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301278 int i, num_devices = 0;
1279 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001280 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1281
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001282 if (snd_device < SND_DEVICE_MIN ||
1283 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001284 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001285 return -EINVAL;
1286 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001287
1288 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1289 ALOGE("%s: Invalid sound device returned", __func__);
1290 return -EINVAL;
1291 }
1292
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001293 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1294 ALOGE("%s: device ref cnt is already 0", __func__);
1295 return -EINVAL;
1296 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001297
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001298 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001299
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001300
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001301 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001302 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301303
Aalique Grahame22e49102018-12-18 14:23:57 -08001304 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1305
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001306 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1307 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001308 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001309
1310 // when speaker device is disabled, reset swap.
1311 // will be renabled on usecase start
1312 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001313 } else if (platform_split_snd_device(adev->platform,
1314 snd_device,
1315 &num_devices,
1316 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301317 for (i = 0; i < num_devices; i++) {
1318 disable_snd_device(adev, new_snd_devices[i]);
1319 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001320 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001321 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001322 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001323 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001324
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001325 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301326 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001327 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001328 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001329 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001330 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301331 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001332 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301333 adev->native_playback_enabled) {
1334 ALOGD("%s: %d: napb: disabling native mode in hardware",
1335 __func__, __LINE__);
1336 audio_route_reset_and_update_path(adev->audio_route,
1337 "true-native-mode");
1338 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001339 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301340 adev->asrc_mode_enabled) {
1341 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301342 disable_asrc_mode(adev);
1343 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001344 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301345 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001346 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001347 ALOGD("%s: deinit ec ref loopback", __func__);
1348 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1349 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001350
1351 audio_extn_utils_release_snd_device(snd_device);
1352 } else {
1353 if (platform_split_snd_device(adev->platform,
1354 snd_device,
1355 &num_devices,
1356 new_snd_devices) == 0) {
1357 for (i = 0; i < num_devices; i++) {
1358 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1359 }
1360 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001361 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001362
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001363 return 0;
1364}
1365
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001366/*
1367 legend:
1368 uc - existing usecase
1369 new_uc - new usecase
1370 d1, d11, d2 - SND_DEVICE enums
1371 a1, a2 - corresponding ANDROID device enums
1372 B1, B2 - backend strings
1373
1374case 1
1375 uc->dev d1 (a1) B1
1376 new_uc->dev d1 (a1), d2 (a2) B1, B2
1377
1378 resolution: disable and enable uc->dev on d1
1379
1380case 2
1381 uc->dev d1 (a1) B1
1382 new_uc->dev d11 (a1) B1
1383
1384 resolution: need to switch uc since d1 and d11 are related
1385 (e.g. speaker and voice-speaker)
1386 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1387
1388case 3
1389 uc->dev d1 (a1) B1
1390 new_uc->dev d2 (a2) B2
1391
1392 resolution: no need to switch uc
1393
1394case 4
1395 uc->dev d1 (a1) B1
1396 new_uc->dev d2 (a2) B1
1397
1398 resolution: disable enable uc-dev on d2 since backends match
1399 we cannot enable two streams on two different devices if they
1400 share the same backend. e.g. if offload is on speaker device using
1401 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1402 using the same backend, offload must also be switched to voice-handset.
1403
1404case 5
1405 uc->dev d1 (a1) B1
1406 new_uc->dev d1 (a1), d2 (a2) B1
1407
1408 resolution: disable enable uc-dev on d2 since backends match
1409 we cannot enable two streams on two different devices if they
1410 share the same backend.
1411
1412case 6
1413 uc->dev d1 (a1) B1
1414 new_uc->dev d2 (a1) B2
1415
1416 resolution: no need to switch
1417
1418case 7
1419 uc->dev d1 (a1), d2 (a2) B1, B2
1420 new_uc->dev d1 (a1) B1
1421
1422 resolution: no need to switch
1423
Zhou Song4ba65882018-07-09 14:48:07 +08001424case 8
1425 uc->dev d1 (a1) B1
1426 new_uc->dev d11 (a1), d2 (a2) B1, B2
1427 resolution: compared to case 1, for this case, d1 and d11 are related
1428 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001429*/
1430static snd_device_t derive_playback_snd_device(void * platform,
1431 struct audio_usecase *uc,
1432 struct audio_usecase *new_uc,
1433 snd_device_t new_snd_device)
1434{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301435 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001436
1437 snd_device_t d1 = uc->out_snd_device;
1438 snd_device_t d2 = new_snd_device;
1439
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301440 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301441 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301442 a1 = uc->stream.inout->out_config.devices;
1443 a2 = new_uc->stream.inout->out_config.devices;
1444 break;
1445 default :
1446 a1 = uc->stream.out->devices;
1447 a2 = new_uc->stream.out->devices;
1448 break;
1449 }
1450
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001451 // Treat as a special case when a1 and a2 are not disjoint
1452 if ((a1 != a2) && (a1 & a2)) {
1453 snd_device_t d3[2];
1454 int num_devices = 0;
1455 int ret = platform_split_snd_device(platform,
1456 popcount(a1) > 1 ? d1 : d2,
1457 &num_devices,
1458 d3);
1459 if (ret < 0) {
1460 if (ret != -ENOSYS) {
1461 ALOGW("%s failed to split snd_device %d",
1462 __func__,
1463 popcount(a1) > 1 ? d1 : d2);
1464 }
1465 goto end;
1466 }
1467
1468 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1469 // But if it does happen, we need to give priority to d2 if
1470 // the combo devices active on the existing usecase share a backend.
1471 // This is because we cannot have a usecase active on a combo device
1472 // and a new usecase requests one device in this combo pair.
1473 if (platform_check_backends_match(d3[0], d3[1])) {
1474 return d2; // case 5
1475 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001476 // check if d1 is related to any of d3's
1477 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001478 return d1; // case 1
1479 else
1480 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001481 }
1482 } else {
1483 if (platform_check_backends_match(d1, d2)) {
1484 return d2; // case 2, 4
1485 } else {
1486 return d1; // case 6, 3
1487 }
1488 }
1489
1490end:
1491 return d2; // return whatever was calculated before.
1492}
1493
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001494static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301495 struct audio_usecase *uc_info,
1496 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001497{
1498 struct listnode *node;
1499 struct audio_usecase *usecase;
1500 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301501 snd_device_t uc_derive_snd_device;
1502 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001503 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1504 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001505 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301506 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001507 /*
1508 * This function is to make sure that all the usecases that are active on
1509 * the hardware codec backend are always routed to any one device that is
1510 * handled by the hardware codec.
1511 * For example, if low-latency and deep-buffer usecases are currently active
1512 * on speaker and out_set_parameters(headset) is received on low-latency
1513 * output, then we have to make sure deep-buffer is also switched to headset,
1514 * because of the limitation that both the devices cannot be enabled
1515 * at the same time as they share the same backend.
1516 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001517 /*
1518 * This call is to check if we need to force routing for a particular stream
1519 * If there is a backend configuration change for the device when a
1520 * new stream starts, then ADM needs to be closed and re-opened with the new
1521 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001522 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001523 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001524 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1525 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301526 /* For a2dp device reconfigure all active sessions
1527 * with new AFE encoder format based on a2dp state
1528 */
1529 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1530 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1531 audio_extn_a2dp_is_force_device_switch()) {
1532 force_routing = true;
1533 force_restart_session = true;
1534 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301535 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1536
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001537 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001538 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001539 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001540 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1541 switch_device[i] = false;
1542
1543 list_for_each(node, &adev->usecase_list) {
1544 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001545
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301546 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1547 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301548 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301549 platform_get_snd_device_name(usecase->out_snd_device),
1550 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301551 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1552 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1553 usecase, uc_info, snd_device);
1554 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1555 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1556 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1557 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001558 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301559 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1560 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1561 ((force_restart_session) ||
1562 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301563 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1564 __func__, use_case_table[usecase->id],
1565 platform_get_snd_device_name(usecase->out_snd_device));
1566 disable_audio_route(adev, usecase);
1567 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301568 /* Enable existing usecase on derived playback device */
1569 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301570 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301571 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001572 }
1573 }
1574
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301575 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1576 num_uc_to_switch);
1577
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001578 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001579 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001580
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301581 /* Make sure the previous devices to be disabled first and then enable the
1582 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001583 list_for_each(node, &adev->usecase_list) {
1584 usecase = node_to_item(node, struct audio_usecase, list);
1585 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001586 /* Check if output sound device to be switched can be split and if any
1587 of the split devices match with derived sound device */
1588 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1589 &num_devices, split_snd_devices) == 0) {
1590 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1591 for (i = 0; i < num_devices; i++) {
1592 /* Disable devices that do not match with derived sound device */
1593 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1594 disable_snd_device(adev, split_snd_devices[i]);
1595 }
1596 } else {
1597 disable_snd_device(adev, usecase->out_snd_device);
1598 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001599 }
1600 }
1601
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001602 list_for_each(node, &adev->usecase_list) {
1603 usecase = node_to_item(node, struct audio_usecase, list);
1604 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001605 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1606 &num_devices, split_snd_devices) == 0) {
1607 /* Enable derived sound device only if it does not match with
1608 one of the split sound devices. This is because the matching
1609 sound device was not disabled */
1610 bool should_enable = true;
1611 for (i = 0; i < num_devices; i++) {
1612 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1613 should_enable = false;
1614 break;
1615 }
1616 }
1617 if (should_enable)
1618 enable_snd_device(adev, derive_snd_device[usecase->id]);
1619 } else {
1620 enable_snd_device(adev, derive_snd_device[usecase->id]);
1621 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001622 }
1623 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001624
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001625 /* Re-route all the usecases on the shared backend other than the
1626 specified usecase to new snd devices */
1627 list_for_each(node, &adev->usecase_list) {
1628 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301629 /* Update the out_snd_device only before enabling the audio route */
1630 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301631 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301632 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301633 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301634 use_case_table[usecase->id],
1635 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001636 /* Update voc calibration before enabling VoIP route */
1637 if (usecase->type == VOIP_CALL)
1638 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001639 usecase->out_snd_device,
1640 platform_get_input_snd_device(
1641 adev->platform, NULL,
1642 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301643 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301644 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001645 out_set_voip_volume(&usecase->stream.out->stream,
1646 usecase->stream.out->volume_l,
1647 usecase->stream.out->volume_r);
1648 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301649 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001650 }
1651 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001652 }
1653}
1654
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301655static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001656 struct audio_usecase *uc_info,
1657 snd_device_t snd_device)
1658{
1659 struct listnode *node;
1660 struct audio_usecase *usecase;
1661 bool switch_device[AUDIO_USECASE_MAX];
1662 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301663 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001664 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001665
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301666 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1667 snd_device);
1668 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301669
1670 /*
1671 * Make sure out devices is checked against out codec backend device and
1672 * also in devices against in codec backend. Checking out device against in
1673 * codec backend or vice versa causes issues.
1674 */
1675 if (uc_info->type == PCM_CAPTURE)
1676 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001677 /*
1678 * This function is to make sure that all the active capture usecases
1679 * are always routed to the same input sound device.
1680 * For example, if audio-record and voice-call usecases are currently
1681 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1682 * is received for voice call then we have to make sure that audio-record
1683 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1684 * because of the limitation that two devices cannot be enabled
1685 * at the same time if they share the same backend.
1686 */
1687 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1688 switch_device[i] = false;
1689
1690 list_for_each(node, &adev->usecase_list) {
1691 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301692 /*
1693 * TODO: Enhance below condition to handle BT sco/USB multi recording
1694 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001695 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001696 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301697 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301698 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301699 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301700 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001701 ((uc_info->type == VOICE_CALL &&
1702 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1703 platform_check_backends_match(snd_device,\
1704 usecase->in_snd_device)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001705 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001706 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1707 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001708 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001709 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001710 switch_device[usecase->id] = true;
1711 num_uc_to_switch++;
1712 }
1713 }
1714
1715 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001716 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001717
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301718 /* Make sure the previous devices to be disabled first and then enable the
1719 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001720 list_for_each(node, &adev->usecase_list) {
1721 usecase = node_to_item(node, struct audio_usecase, list);
1722 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001723 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001724 }
1725 }
1726
1727 list_for_each(node, &adev->usecase_list) {
1728 usecase = node_to_item(node, struct audio_usecase, list);
1729 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001730 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001731 }
1732 }
1733
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001734 /* Re-route all the usecases on the shared backend other than the
1735 specified usecase to new snd devices */
1736 list_for_each(node, &adev->usecase_list) {
1737 usecase = node_to_item(node, struct audio_usecase, list);
1738 /* Update the in_snd_device only before enabling the audio route */
1739 if (switch_device[usecase->id] ) {
1740 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001741 if (usecase->type != VOICE_CALL) {
1742 /* Update voc calibration before enabling VoIP route */
1743 if (usecase->type == VOIP_CALL)
1744 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001745 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001746 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301747 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001748 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001749 }
1750 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001751 }
1752}
1753
Mingming Yin3a941d42016-02-17 18:08:05 -08001754static void reset_hdmi_sink_caps(struct stream_out *out) {
1755 int i = 0;
1756
1757 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1758 out->supported_channel_masks[i] = 0;
1759 }
1760 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1761 out->supported_formats[i] = 0;
1762 }
1763 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1764 out->supported_sample_rates[i] = 0;
1765 }
1766}
1767
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001769static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001770{
Mingming Yin3a941d42016-02-17 18:08:05 -08001771 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001772 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773
Mingming Yin3a941d42016-02-17 18:08:05 -08001774 reset_hdmi_sink_caps(out);
1775
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001776 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001777 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001778 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001779 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001780 }
1781
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001782 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001783 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001784 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001785 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001786 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1787 case 6:
1788 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1789 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1790 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1791 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1792 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1793 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001794 break;
1795 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001796 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001797 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001798 break;
1799 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001800
1801 // check channel format caps
1802 i = 0;
1803 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1804 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1805 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1806 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1807 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1808 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1809 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1810 }
1811
Ben Romberger1aaaf862017-04-06 17:49:46 -07001812 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1813 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1814 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1815 }
1816
Mingming Yin3a941d42016-02-17 18:08:05 -08001817 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1818 ALOGV(":%s HDMI supports DTS format", __func__);
1819 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1820 }
1821
1822 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1823 ALOGV(":%s HDMI supports DTS HD format", __func__);
1824 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1825 }
1826
Naresh Tanniru928f0862017-04-07 16:44:23 -07001827 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1828 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1829 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1830 }
1831
Mingming Yin3a941d42016-02-17 18:08:05 -08001832
1833 // check sample rate caps
1834 i = 0;
1835 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1836 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1837 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1838 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1839 }
1840 }
1841
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001842 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001843}
1844
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001845static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1846 uint32_t *supported_sample_rates __unused,
1847 uint32_t max_rates __unused)
1848{
1849 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1850 supported_sample_rates,
1851 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301852 ssize_t i = 0;
1853
1854 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001855 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1856 supported_sample_rates[i]);
1857 }
1858 return count;
1859}
1860
1861static inline int read_usb_sup_channel_masks(bool is_playback,
1862 audio_channel_mask_t *supported_channel_masks,
1863 uint32_t max_masks)
1864{
1865 int channels = audio_extn_usb_get_max_channels(is_playback);
1866 int channel_count;
1867 uint32_t num_masks = 0;
1868 if (channels > MAX_HIFI_CHANNEL_COUNT)
1869 channels = MAX_HIFI_CHANNEL_COUNT;
1870
1871 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001872 // start from 2 channels as framework currently doesn't support mono.
1873 if (channels >= FCC_2) {
1874 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1875 }
1876 for (channel_count = FCC_2;
1877 channel_count <= channels && num_masks < max_masks;
1878 ++channel_count) {
1879 supported_channel_masks[num_masks++] =
1880 audio_channel_mask_for_index_assignment_from_count(channel_count);
1881 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001882 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001883 // For capture we report all supported channel masks from 1 channel up.
1884 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001885 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1886 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001887 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1888 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1889 if (channel_count <= FCC_2) {
1890 mask = audio_channel_in_mask_from_count(channel_count);
1891 supported_channel_masks[num_masks++] = mask;
1892 }
1893 const audio_channel_mask_t index_mask =
1894 audio_channel_mask_for_index_assignment_from_count(channel_count);
1895 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1896 supported_channel_masks[num_masks++] = index_mask;
1897 }
1898 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001899 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301900
vincenttewf51c94e2019-05-07 10:28:53 +08001901 for (size_t i = 0; i < num_masks; ++i) {
1902 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1903 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301904 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001905 return num_masks;
1906}
1907
1908static inline int read_usb_sup_formats(bool is_playback __unused,
1909 audio_format_t *supported_formats,
1910 uint32_t max_formats __unused)
1911{
1912 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1913 switch (bitwidth) {
1914 case 24:
1915 // XXX : usb.c returns 24 for s24 and s24_le?
1916 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1917 break;
1918 case 32:
1919 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1920 break;
1921 case 16:
1922 default :
1923 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1924 break;
1925 }
1926 ALOGV("%s: %s supported format %d", __func__,
1927 is_playback ? "P" : "C", bitwidth);
1928 return 1;
1929}
1930
1931static inline int read_usb_sup_params_and_compare(bool is_playback,
1932 audio_format_t *format,
1933 audio_format_t *supported_formats,
1934 uint32_t max_formats,
1935 audio_channel_mask_t *mask,
1936 audio_channel_mask_t *supported_channel_masks,
1937 uint32_t max_masks,
1938 uint32_t *rate,
1939 uint32_t *supported_sample_rates,
1940 uint32_t max_rates) {
1941 int ret = 0;
1942 int num_formats;
1943 int num_masks;
1944 int num_rates;
1945 int i;
1946
1947 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1948 max_formats);
1949 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1950 max_masks);
1951
1952 num_rates = read_usb_sup_sample_rates(is_playback,
1953 supported_sample_rates, max_rates);
1954
1955#define LUT(table, len, what, dflt) \
1956 for (i=0; i<len && (table[i] != what); i++); \
1957 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1958
1959 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1960 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1961 LUT(supported_sample_rates, num_rates, *rate, 0);
1962
1963#undef LUT
1964 return ret < 0 ? -EINVAL : 0; // HACK TBD
1965}
1966
Alexy Josephb1379942016-01-29 15:49:38 -08001967audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001968 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001969{
1970 struct audio_usecase *usecase;
1971 struct listnode *node;
1972
1973 list_for_each(node, &adev->usecase_list) {
1974 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001975 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001976 ALOGV("%s: usecase id %d", __func__, usecase->id);
1977 return usecase->id;
1978 }
1979 }
1980 return USECASE_INVALID;
1981}
1982
Alexy Josephb1379942016-01-29 15:49:38 -08001983struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001984 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001985{
1986 struct audio_usecase *usecase;
1987 struct listnode *node;
1988
1989 list_for_each(node, &adev->usecase_list) {
1990 usecase = node_to_item(node, struct audio_usecase, list);
1991 if (usecase->id == uc_id)
1992 return usecase;
1993 }
1994 return NULL;
1995}
1996
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301997/*
1998 * is a true native playback active
1999 */
2000bool audio_is_true_native_stream_active(struct audio_device *adev)
2001{
2002 bool active = false;
2003 int i = 0;
2004 struct listnode *node;
2005
2006 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2007 ALOGV("%s:napb: not in true mode or non hdphones device",
2008 __func__);
2009 active = false;
2010 goto exit;
2011 }
2012
2013 list_for_each(node, &adev->usecase_list) {
2014 struct audio_usecase *uc;
2015 uc = node_to_item(node, struct audio_usecase, list);
2016 struct stream_out *curr_out =
2017 (struct stream_out*) uc->stream.out;
2018
2019 if (curr_out && PCM_PLAYBACK == uc->type) {
2020 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2021 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2022 uc->id, curr_out->sample_rate,
2023 curr_out->bit_width,
2024 platform_get_snd_device_name(uc->out_snd_device));
2025
2026 if (is_offload_usecase(uc->id) &&
2027 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2028 active = true;
2029 ALOGD("%s:napb:native stream detected", __func__);
2030 }
2031 }
2032 }
2033exit:
2034 return active;
2035}
2036
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002037uint32_t adev_get_dsp_bit_width_enforce_mode()
2038{
2039 if (adev == NULL) {
2040 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2041 return 0;
2042 }
2043 return adev->dsp_bit_width_enforce_mode;
2044}
2045
2046static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2047{
2048 char value[PROPERTY_VALUE_MAX];
2049 int trial;
2050 uint32_t dsp_bit_width_enforce_mode = 0;
2051
2052 if (!mixer) {
2053 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2054 __func__);
2055 return 0;
2056 }
2057
2058 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2059 value, NULL) > 0) {
2060 trial = atoi(value);
2061 switch (trial) {
2062 case 16:
2063 dsp_bit_width_enforce_mode = 16;
2064 break;
2065 case 24:
2066 dsp_bit_width_enforce_mode = 24;
2067 break;
2068 case 32:
2069 dsp_bit_width_enforce_mode = 32;
2070 break;
2071 default:
2072 dsp_bit_width_enforce_mode = 0;
2073 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2074 break;
2075 }
2076 }
2077
2078 return dsp_bit_width_enforce_mode;
2079}
2080
2081static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2082 uint32_t enforce_mode,
2083 bool enable)
2084{
2085 struct mixer_ctl *ctl = NULL;
2086 const char *mixer_ctl_name = "ASM Bit Width";
2087 uint32_t asm_bit_width_mode = 0;
2088
2089 if (enforce_mode == 0) {
2090 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2091 return;
2092 }
2093
2094 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2095 if (!ctl) {
2096 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2097 __func__, mixer_ctl_name);
2098 return;
2099 }
2100
2101 if (enable)
2102 asm_bit_width_mode = enforce_mode;
2103 else
2104 asm_bit_width_mode = 0;
2105
2106 ALOGV("%s DSP bit width feature status is %d width=%d",
2107 __func__, enable, asm_bit_width_mode);
2108 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2109 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2110 asm_bit_width_mode);
2111
2112 return;
2113}
2114
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302115/*
2116 * if native DSD playback active
2117 */
2118bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2119{
2120 bool active = false;
2121 struct listnode *node = NULL;
2122 struct audio_usecase *uc = NULL;
2123 struct stream_out *curr_out = NULL;
2124
2125 list_for_each(node, &adev->usecase_list) {
2126 uc = node_to_item(node, struct audio_usecase, list);
2127 curr_out = (struct stream_out*) uc->stream.out;
2128
2129 if (curr_out && PCM_PLAYBACK == uc->type &&
2130 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2131 active = true;
2132 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302133 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302134 }
2135 }
2136 return active;
2137}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302138
2139static bool force_device_switch(struct audio_usecase *usecase)
2140{
2141 bool ret = false;
2142 bool is_it_true_mode = false;
2143
Zhou Song30f2c3e2018-02-08 14:02:15 +08002144 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302145 usecase->type == TRANSCODE_LOOPBACK_RX ||
2146 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002147 return false;
2148 }
2149
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002150 if(usecase->stream.out == NULL) {
2151 ALOGE("%s: stream.out is NULL", __func__);
2152 return false;
2153 }
2154
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302155 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002156 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2157 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2158 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302159 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2160 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2161 (!is_it_true_mode && adev->native_playback_enabled)){
2162 ret = true;
2163 ALOGD("napb: time to toggle native mode");
2164 }
2165 }
2166
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302167 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302168 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2169 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002170 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302171 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302172 ALOGD("Force a2dp device switch to update new encoder config");
2173 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002174 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302175
Florian Pfister1a84f312018-07-19 14:38:18 +02002176 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302177 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2178 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002179 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302180 return ret;
2181}
2182
Aalique Grahame22e49102018-12-18 14:23:57 -08002183static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2184{
2185 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2186}
2187
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302188bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2189{
2190 bool ret=false;
2191 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2192 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2193 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2194 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2195 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2196 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2197 ret = true;
2198
2199 return ret;
2200}
2201
2202bool is_a2dp_device(snd_device_t out_snd_device)
2203{
2204 bool ret=false;
2205 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2206 ret = true;
2207
2208 return ret;
2209}
2210
2211bool is_bt_soc_on(struct audio_device *adev)
2212{
2213 struct mixer_ctl *ctl;
2214 char *mixer_ctl_name = "BT SOC status";
2215 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2216 bool bt_soc_status = true;
2217 if (!ctl) {
2218 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2219 __func__, mixer_ctl_name);
2220 /*This is to ensure we dont break targets which dont have the kernel change*/
2221 return true;
2222 }
2223 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2224 ALOGD("BT SOC status: %d",bt_soc_status);
2225 return bt_soc_status;
2226}
2227
2228int out_standby_l(struct audio_stream *stream);
2229
Eric Laurent637e2d42018-11-15 12:24:31 -08002230struct stream_in *adev_get_active_input(const struct audio_device *adev)
2231{
2232 struct listnode *node;
2233 struct stream_in *last_active_in = NULL;
2234
2235 /* Get last added active input.
2236 * TODO: We may use a priority mechanism to pick highest priority active source */
2237 list_for_each(node, &adev->usecase_list)
2238 {
2239 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2240 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2241 last_active_in = usecase->stream.in;
2242 }
2243
2244 return last_active_in;
2245}
2246
2247struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2248{
2249 struct listnode *node;
2250
2251 /* First check active inputs with voice communication source and then
2252 * any input if audio mode is in communication */
2253 list_for_each(node, &adev->usecase_list)
2254 {
2255 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2256 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2257 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2258 return usecase->stream.in;
2259 }
2260 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2261 return adev_get_active_input(adev);
2262
2263 return NULL;
2264}
2265
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002266int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002267{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002268 snd_device_t out_snd_device = SND_DEVICE_NONE;
2269 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002270 struct audio_usecase *usecase = NULL;
2271 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002272 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002273 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302274 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002275 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002276 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002277
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302278 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2279
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002280 usecase = get_usecase_from_list(adev, uc_id);
2281 if (usecase == NULL) {
2282 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2283 return -EINVAL;
2284 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002285
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002286 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002287 (usecase->type == VOIP_CALL) ||
2288 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302289 if(usecase->stream.out == NULL) {
2290 ALOGE("%s: stream.out is NULL", __func__);
2291 return -EINVAL;
2292 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002293 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002294 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002295 in_snd_device = platform_get_input_snd_device(adev->platform,
2296 NULL,
2297 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002298 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302299 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302300 if (usecase->stream.inout == NULL) {
2301 ALOGE("%s: stream.inout is NULL", __func__);
2302 return -EINVAL;
2303 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302304 stream_out.devices = usecase->stream.inout->out_config.devices;
2305 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2306 stream_out.format = usecase->stream.inout->out_config.format;
2307 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2308 out_snd_device = platform_get_output_snd_device(adev->platform,
2309 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302310 usecase->devices = out_snd_device;
2311 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2312 if (usecase->stream.inout == NULL) {
2313 ALOGE("%s: stream.inout is NULL", __func__);
2314 return -EINVAL;
2315 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002316 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302317 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002318 } else {
2319 /*
2320 * If the voice call is active, use the sound devices of voice call usecase
2321 * so that it would not result any device switch. All the usecases will
2322 * be switched to new device when select_devices() is called for voice call
2323 * usecase. This is to avoid switching devices for voice call when
2324 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002325 * choose voice call device only if the use case device is
2326 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002327 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002328 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002329 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002330 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002331 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2332 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302333 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2334 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002335 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2336 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002337 in_snd_device = vc_usecase->in_snd_device;
2338 out_snd_device = vc_usecase->out_snd_device;
2339 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002340 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002341 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002342 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002343 if ((voip_usecase != NULL) &&
2344 (usecase->type == PCM_PLAYBACK) &&
2345 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002346 out_snd_device_backend_match = platform_check_backends_match(
2347 voip_usecase->out_snd_device,
2348 platform_get_output_snd_device(
2349 adev->platform,
2350 usecase->stream.out));
2351 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002352 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002353 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2354 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002355 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002356 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002357 in_snd_device = voip_usecase->in_snd_device;
2358 out_snd_device = voip_usecase->out_snd_device;
2359 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002360 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002361 hfp_ucid = audio_extn_hfp_get_usecase();
2362 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002363 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002364 in_snd_device = hfp_usecase->in_snd_device;
2365 out_snd_device = hfp_usecase->out_snd_device;
2366 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002367 }
2368 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302369 if (usecase->stream.out == NULL) {
2370 ALOGE("%s: stream.out is NULL", __func__);
2371 return -EINVAL;
2372 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002373 usecase->devices = usecase->stream.out->devices;
2374 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002375 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002376 struct stream_out *voip_out = adev->primary_output;
2377 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002378 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002379 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002380 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002381
Eric Laurent637e2d42018-11-15 12:24:31 -08002382 if (voip_usecase)
2383 voip_out = voip_usecase->stream.out;
2384
2385 if (usecase->stream.out == voip_out && voip_in != NULL)
2386 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002387 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002388 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302389 if (usecase->stream.in == NULL) {
2390 ALOGE("%s: stream.in is NULL", __func__);
2391 return -EINVAL;
2392 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002393 usecase->devices = usecase->stream.in->device;
2394 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002395 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002396 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002397 struct stream_in *voip_in = get_voice_communication_input(adev);
2398
2399 if (voip_in != NULL) {
2400
2401 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2402 USECASE_AUDIO_PLAYBACK_VOIP);
2403
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002404 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Eric Laurent637e2d42018-11-15 12:24:31 -08002405 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2406 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2407 } else if (voip_usecase) {
2408 out_device = voip_usecase->stream.out->devices;
2409 } else if (adev->primary_output &&
2410 !adev->primary_output->standby) {
2411 out_device = adev->primary_output->devices;
2412 } else {
2413 /* forcing speaker o/p device to get matching i/p pair
2414 in case o/p is not routed from same primary HAL */
2415 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2416 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002417 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002418 in_snd_device = platform_get_input_snd_device(adev->platform,
2419 usecase->stream.in,
2420 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002421 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002422 }
2423 }
2424
2425 if (out_snd_device == usecase->out_snd_device &&
2426 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302427
2428 if (!force_device_switch(usecase))
2429 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002430 }
2431
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302432 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002433 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302434 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2435 return 0;
2436 }
2437
Aalique Grahame22e49102018-12-18 14:23:57 -08002438 if (out_snd_device != SND_DEVICE_NONE &&
2439 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2440 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2441 __func__,
2442 use_case_table[uc_id],
2443 adev->last_logged_snd_device[uc_id][0],
2444 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2445 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2446 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2447 -1,
2448 out_snd_device,
2449 platform_get_snd_device_name(out_snd_device),
2450 platform_get_snd_device_acdb_id(out_snd_device));
2451 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2452 }
2453 if (in_snd_device != SND_DEVICE_NONE &&
2454 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2455 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2456 __func__,
2457 use_case_table[uc_id],
2458 adev->last_logged_snd_device[uc_id][1],
2459 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2460 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2461 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2462 -1,
2463 in_snd_device,
2464 platform_get_snd_device_name(in_snd_device),
2465 platform_get_snd_device_acdb_id(in_snd_device));
2466 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2467 }
2468
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002469
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002470 /*
2471 * Limitation: While in call, to do a device switch we need to disable
2472 * and enable both RX and TX devices though one of them is same as current
2473 * device.
2474 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002475 if ((usecase->type == VOICE_CALL) &&
2476 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2477 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002478 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002479 }
2480
2481 if (((usecase->type == VOICE_CALL) ||
2482 (usecase->type == VOIP_CALL)) &&
2483 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2484 /* Disable sidetone only if voice/voip call already exists */
2485 if (voice_is_call_state_active(adev) ||
2486 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002487 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002488
2489 /* Disable aanc only if voice call exists */
2490 if (voice_is_call_state_active(adev))
2491 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002492 }
2493
Aalique Grahame22e49102018-12-18 14:23:57 -08002494 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2495 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002496 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302497 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002498 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2499 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2500 else
2501 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302502 }
2503
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002504 /* Disable current sound devices */
2505 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002506 disable_audio_route(adev, usecase);
2507 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508 }
2509
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002510 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002511 disable_audio_route(adev, usecase);
2512 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002513 }
2514
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002515 /* Applicable only on the targets that has external modem.
2516 * New device information should be sent to modem before enabling
2517 * the devices to reduce in-call device switch time.
2518 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002519 if ((usecase->type == VOICE_CALL) &&
2520 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2521 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002522 status = platform_switch_voice_call_enable_device_config(adev->platform,
2523 out_snd_device,
2524 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002525 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002526
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002527 /* Enable new sound devices */
2528 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002529 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302530 if (platform_check_codec_asrc_support(adev->platform))
2531 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002532 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002533 }
2534
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002535 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302536 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002537 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002538 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002539
Avinash Vaish71a8b972014-07-24 15:36:33 +05302540 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002541 status = platform_switch_voice_call_device_post(adev->platform,
2542 out_snd_device,
2543 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302544 enable_audio_route_for_voice_usecases(adev, usecase);
2545 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002546
sangwoo170731f2013-06-08 15:36:36 +09002547 usecase->in_snd_device = in_snd_device;
2548 usecase->out_snd_device = out_snd_device;
2549
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302550 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2551 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302552 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002553 if ((24 == usecase->stream.out->bit_width) &&
2554 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2555 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2556 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2557 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2558 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2559 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2560 /*
2561 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2562 * configured device sample rate, if not update the COPP rate to be equal to the
2563 * device sample rate, else open COPP at stream sample rate
2564 */
2565 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2566 usecase->stream.out->sample_rate,
2567 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302568 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2569 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002570 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2571 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2572 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2573 }
2574
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002575 /* Notify device change info to effect clients registered */
2576 audio_extn_gef_notify_device_config(
2577 usecase->stream.out->devices,
2578 usecase->stream.out->channel_mask,
2579 usecase->stream.out->app_type_cfg.sample_rate,
2580 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302581 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002582 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002583
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002584 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002585
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002586 /* If input stream is already running then effect needs to be
2587 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002588 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002589 check_and_enable_effect(adev);
2590
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002591 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002592 /* Enable aanc only if voice call exists */
2593 if (voice_is_call_state_active(adev))
2594 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2595
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002596 /* Enable sidetone only if other voice/voip call already exists */
2597 if (voice_is_call_state_active(adev) ||
2598 voice_extn_compress_voip_is_started(adev))
2599 voice_set_sidetone(adev, out_snd_device, true);
2600 }
2601
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002602 /* Applicable only on the targets that has external modem.
2603 * Enable device command should be sent to modem only after
2604 * enabling voice call mixer controls
2605 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002606 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002607 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2608 out_snd_device,
2609 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302610
2611 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002612 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302613 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002614 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302615 if (is_bt_soc_on(adev) == false){
2616 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002617 if (in->pcm != NULL)
2618 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302619 }
2620 }
2621 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2622 && usecase->stream.out->started) {
2623 if (is_bt_soc_on(adev) == false) {
2624 ALOGD("BT SCO/A2DP disconnected while in connection");
2625 out_standby_l(&usecase->stream.out->stream.common);
2626 }
2627 }
2628 } else if ((usecase->stream.out != NULL) &&
2629 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302630 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2631 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302632 usecase->stream.out->started) {
2633 if (is_bt_soc_on(adev) == false) {
2634 ALOGD("BT SCO/A2dp disconnected while in connection");
2635 out_standby_l(&usecase->stream.out->stream.common);
2636 }
2637 }
2638 }
2639
Yung Ti Su70cb8242018-06-22 17:38:47 +08002640 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002641 struct stream_out *voip_out = voip_usecase->stream.out;
2642 audio_extn_utils_send_app_type_gain(adev,
2643 voip_out->app_type_cfg.app_type,
2644 &voip_out->app_type_cfg.gain[0]);
2645 }
2646
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302647 ALOGD("%s: done",__func__);
2648
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 return status;
2650}
2651
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652static int stop_input_stream(struct stream_in *in)
2653{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302654 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002655 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302656
2657 if (in == NULL) {
2658 ALOGE("%s: stream_in ptr is NULL", __func__);
2659 return -EINVAL;
2660 }
2661
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662 struct audio_device *adev = in->dev;
2663
Eric Laurent994a6932013-07-17 11:51:42 -07002664 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002665 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002666 uc_info = get_usecase_from_list(adev, in->usecase);
2667 if (uc_info == NULL) {
2668 ALOGE("%s: Could not find the usecase (%d) in the list",
2669 __func__, in->usecase);
2670 return -EINVAL;
2671 }
2672
Derek Chenea197282019-01-07 17:35:01 -08002673 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2674 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002675
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002676 /* Close in-call recording streams */
2677 voice_check_and_stop_incall_rec_usecase(adev, in);
2678
Eric Laurent150dbfe2013-02-27 14:31:02 -08002679 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002680 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002681
2682 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002683 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002684
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002685 list_remove(&uc_info->list);
2686 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002687
Vatsal Buchac09ae062018-11-14 13:25:08 +05302688 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002689 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002690 return ret;
2691}
2692
2693int start_input_stream(struct stream_in *in)
2694{
2695 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002696 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302698
2699 if (in == NULL) {
2700 ALOGE("%s: stream_in ptr is NULL", __func__);
2701 return -EINVAL;
2702 }
2703
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002704 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002705 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002706 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002707
Mingming Yin2664a5b2015-09-03 10:53:11 -07002708 if (get_usecase_from_list(adev, usecase) == NULL)
2709 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302710 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2711 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002712
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302713 if (CARD_STATUS_OFFLINE == in->card_status||
2714 CARD_STATUS_OFFLINE == adev->card_status) {
2715 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302716 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302717 goto error_config;
2718 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302719
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302720 if (audio_is_bluetooth_sco_device(in->device)) {
2721 if (!adev->bt_sco_on) {
2722 ALOGE("%s: SCO profile is not ready, return error", __func__);
2723 ret = -EIO;
2724 goto error_config;
2725 }
2726 }
2727
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002728 /* Check if source matches incall recording usecase criteria */
2729 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2730 if (ret)
2731 goto error_config;
2732 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002733 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2734
2735 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2736 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2737 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002738 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002739 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002740
Eric Laurentb23d5282013-05-14 15:27:20 -07002741 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742 if (in->pcm_device_id < 0) {
2743 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2744 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002745 ret = -EINVAL;
2746 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002747 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002749 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002750
2751 if (!uc_info) {
2752 ret = -ENOMEM;
2753 goto error_config;
2754 }
2755
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002756 uc_info->id = in->usecase;
2757 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002758 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002759 uc_info->devices = in->device;
2760 uc_info->in_snd_device = SND_DEVICE_NONE;
2761 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002762
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002763 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002764 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302765 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2766 adev->perf_lock_opts,
2767 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002768 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769
Derek Chenea197282019-01-07 17:35:01 -08002770 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2771 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002772
Haynes Mathew George16081042017-05-31 17:16:49 -07002773 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302774 ret = audio_extn_cin_start_input_stream(in);
2775 if (ret)
2776 goto error_open;
2777 else
2778 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002779 }
2780
Haynes Mathew George16081042017-05-31 17:16:49 -07002781 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002782 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002783 ALOGE("%s: pcm stream not ready", __func__);
2784 goto error_open;
2785 }
2786 ret = pcm_start(in->pcm);
2787 if (ret < 0) {
2788 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2789 goto error_open;
2790 }
2791 } else {
2792 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2793 unsigned int pcm_open_retry_count = 0;
2794
2795 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2796 flags |= PCM_MMAP | PCM_NOIRQ;
2797 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2798 } else if (in->realtime) {
2799 flags |= PCM_MMAP | PCM_NOIRQ;
2800 }
2801
Garmond Leunge2433c32017-09-28 21:51:22 -07002802 if (audio_extn_ffv_get_stream() == in) {
2803 ALOGD("%s: ffv stream, update pcm config", __func__);
2804 audio_extn_ffv_update_pcm_config(&config);
2805 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002806 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2807 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2808
2809 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002810 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002811 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002812 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002813 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302814 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302815 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2816 adev->card_status = CARD_STATUS_OFFLINE;
2817 in->card_status = CARD_STATUS_OFFLINE;
2818 ret = -EIO;
2819 goto error_open;
2820 }
2821
Haynes Mathew George16081042017-05-31 17:16:49 -07002822 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2823 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2824 if (in->pcm != NULL) {
2825 pcm_close(in->pcm);
2826 in->pcm = NULL;
2827 }
2828 if (pcm_open_retry_count-- == 0) {
2829 ret = -EIO;
2830 goto error_open;
2831 }
2832 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2833 continue;
2834 }
2835 break;
2836 }
2837
2838 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002839 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002840 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002841 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002842 if (ret < 0) {
2843 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2844 pcm_close(in->pcm);
2845 in->pcm = NULL;
2846 goto error_open;
2847 }
2848 register_in_stream(in);
2849 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002850 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002851 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002852 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002853 if (ret < 0) {
2854 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002855 pcm_close(in->pcm);
2856 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002857 goto error_open;
2858 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002859 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002860 }
2861
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002862 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07002863 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
2864 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002865
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302866done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08002867 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302868 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002869 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302870 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002871 return ret;
2872
2873error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08002874 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302875 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002877
Eric Laurentc8400632013-02-14 19:04:54 -08002878error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302879 /*
2880 * sleep 50ms to allow sufficient time for kernel
2881 * drivers to recover incases like SSR.
2882 */
2883 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002884 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302885 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002886 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002887}
2888
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002889void lock_input_stream(struct stream_in *in)
2890{
2891 pthread_mutex_lock(&in->pre_lock);
2892 pthread_mutex_lock(&in->lock);
2893 pthread_mutex_unlock(&in->pre_lock);
2894}
2895
2896void lock_output_stream(struct stream_out *out)
2897{
2898 pthread_mutex_lock(&out->pre_lock);
2899 pthread_mutex_lock(&out->lock);
2900 pthread_mutex_unlock(&out->pre_lock);
2901}
2902
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002903/* must be called with out->lock locked */
2904static int send_offload_cmd_l(struct stream_out* out, int command)
2905{
2906 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2907
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002908 if (!cmd) {
2909 ALOGE("failed to allocate mem for command 0x%x", command);
2910 return -ENOMEM;
2911 }
2912
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002913 ALOGVV("%s %d", __func__, command);
2914
2915 cmd->cmd = command;
2916 list_add_tail(&out->offload_cmd_list, &cmd->node);
2917 pthread_cond_signal(&out->offload_cond);
2918 return 0;
2919}
2920
2921/* must be called iwth out->lock locked */
2922static void stop_compressed_output_l(struct stream_out *out)
2923{
2924 out->offload_state = OFFLOAD_STATE_IDLE;
2925 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002926 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002927 if (out->compr != NULL) {
2928 compress_stop(out->compr);
2929 while (out->offload_thread_blocked) {
2930 pthread_cond_wait(&out->cond, &out->lock);
2931 }
2932 }
2933}
2934
Varun Balaraje49253e2017-07-06 19:48:56 +05302935bool is_interactive_usecase(audio_usecase_t uc_id)
2936{
2937 unsigned int i;
2938 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2939 if (uc_id == interactive_usecases[i])
2940 return true;
2941 }
2942 return false;
2943}
2944
2945static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2946{
2947 audio_usecase_t ret_uc = USECASE_INVALID;
2948 unsigned int intract_uc_index;
2949 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2950
2951 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2952 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2953 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2954 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2955 ret_uc = interactive_usecases[intract_uc_index];
2956 break;
2957 }
2958 }
2959
2960 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2961 return ret_uc;
2962}
2963
2964static void free_interactive_usecase(struct audio_device *adev,
2965 audio_usecase_t uc_id)
2966{
2967 unsigned int interact_uc_index;
2968 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2969
2970 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2971 if (interactive_usecases[interact_uc_index] == uc_id) {
2972 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2973 break;
2974 }
2975 }
2976 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2977}
2978
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002979bool is_offload_usecase(audio_usecase_t uc_id)
2980{
2981 unsigned int i;
2982 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2983 if (uc_id == offload_usecases[i])
2984 return true;
2985 }
2986 return false;
2987}
2988
Dhananjay Kumarac341582017-02-23 23:42:25 +05302989static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002990{
vivek mehta446c3962015-09-14 10:57:35 -07002991 audio_usecase_t ret_uc = USECASE_INVALID;
2992 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002993 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002994 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302995 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002996 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2997 else
2998 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002999
vivek mehta446c3962015-09-14 10:57:35 -07003000 pthread_mutex_lock(&adev->lock);
3001 if (get_usecase_from_list(adev, ret_uc) != NULL)
3002 ret_uc = USECASE_INVALID;
3003 pthread_mutex_unlock(&adev->lock);
3004
3005 return ret_uc;
3006 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003007
3008 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003009 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3010 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3011 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3012 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003013 break;
3014 }
3015 }
vivek mehta446c3962015-09-14 10:57:35 -07003016
3017 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3018 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003019}
3020
3021static void free_offload_usecase(struct audio_device *adev,
3022 audio_usecase_t uc_id)
3023{
vivek mehta446c3962015-09-14 10:57:35 -07003024 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003025 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003026
3027 if (!adev->multi_offload_enable)
3028 return;
3029
3030 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3031 if (offload_usecases[offload_uc_index] == uc_id) {
3032 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003033 break;
3034 }
3035 }
3036 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3037}
3038
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003039static void *offload_thread_loop(void *context)
3040{
3041 struct stream_out *out = (struct stream_out *) context;
3042 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003043 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003044
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003045 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003046 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003047 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3048
3049 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003050 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003051 out->offload_state = OFFLOAD_STATE_IDLE;
3052 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003053 for (;;) {
3054 struct offload_cmd *cmd = NULL;
3055 stream_callback_event_t event;
3056 bool send_callback = false;
3057
3058 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3059 __func__, list_empty(&out->offload_cmd_list),
3060 out->offload_state);
3061 if (list_empty(&out->offload_cmd_list)) {
3062 ALOGV("%s SLEEPING", __func__);
3063 pthread_cond_wait(&out->offload_cond, &out->lock);
3064 ALOGV("%s RUNNING", __func__);
3065 continue;
3066 }
3067
3068 item = list_head(&out->offload_cmd_list);
3069 cmd = node_to_item(item, struct offload_cmd, node);
3070 list_remove(item);
3071
3072 ALOGVV("%s STATE %d CMD %d out->compr %p",
3073 __func__, out->offload_state, cmd->cmd, out->compr);
3074
3075 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3076 free(cmd);
3077 break;
3078 }
3079
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003080 // allow OFFLOAD_CMD_ERROR reporting during standby
3081 // this is needed to handle failures during compress_open
3082 // Note however that on a pause timeout, the stream is closed
3083 // and no offload usecase will be active. Therefore this
3084 // special case is needed for compress_open failures alone
3085 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3086 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003087 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003088 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003089 pthread_cond_signal(&out->cond);
3090 continue;
3091 }
3092 out->offload_thread_blocked = true;
3093 pthread_mutex_unlock(&out->lock);
3094 send_callback = false;
3095 switch(cmd->cmd) {
3096 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003097 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003098 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003099 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003100 send_callback = true;
3101 event = STREAM_CBK_EVENT_WRITE_READY;
3102 break;
3103 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003104 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303105 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003106 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303107 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003108 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303109 if (ret < 0)
3110 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303111 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303112 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003113 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003114 else
3115 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003116 if (-ENETRESET != ret && !(-EINTR == ret &&
3117 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303118 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303119 pthread_mutex_lock(&out->lock);
3120 out->send_new_metadata = 1;
3121 out->send_next_track_params = true;
3122 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303123 event = STREAM_CBK_EVENT_DRAIN_READY;
3124 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3125 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303126 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003127 break;
3128 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003129 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003130 ret = compress_drain(out->compr);
3131 ALOGD("copl(%p):out of compress_drain", out);
3132 // EINTR check avoids drain interruption due to SSR
3133 if (-ENETRESET != ret && !(-EINTR == ret &&
3134 CARD_STATUS_OFFLINE == out->card_status)) {
3135 send_callback = true;
3136 event = STREAM_CBK_EVENT_DRAIN_READY;
3137 } else
3138 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303140 case OFFLOAD_CMD_ERROR:
3141 ALOGD("copl(%p): sending error callback to AF", out);
3142 send_callback = true;
3143 event = STREAM_CBK_EVENT_ERROR;
3144 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003145 default:
3146 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3147 break;
3148 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003149 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003150 out->offload_thread_blocked = false;
3151 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003152 if (send_callback && out->client_callback) {
3153 ALOGVV("%s: sending client_callback event %d", __func__, event);
3154 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003155 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003156 free(cmd);
3157 }
3158
3159 pthread_cond_signal(&out->cond);
3160 while (!list_empty(&out->offload_cmd_list)) {
3161 item = list_head(&out->offload_cmd_list);
3162 list_remove(item);
3163 free(node_to_item(item, struct offload_cmd, node));
3164 }
3165 pthread_mutex_unlock(&out->lock);
3166
3167 return NULL;
3168}
3169
3170static int create_offload_callback_thread(struct stream_out *out)
3171{
3172 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3173 list_init(&out->offload_cmd_list);
3174 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3175 offload_thread_loop, out);
3176 return 0;
3177}
3178
3179static int destroy_offload_callback_thread(struct stream_out *out)
3180{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003181 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003182 stop_compressed_output_l(out);
3183 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3184
3185 pthread_mutex_unlock(&out->lock);
3186 pthread_join(out->offload_thread, (void **) NULL);
3187 pthread_cond_destroy(&out->offload_cond);
3188
3189 return 0;
3190}
3191
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192static int stop_output_stream(struct stream_out *out)
3193{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303194 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003195 struct audio_usecase *uc_info;
3196 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003197 bool has_voip_usecase =
3198 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003199
Eric Laurent994a6932013-07-17 11:51:42 -07003200 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003201 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003202 uc_info = get_usecase_from_list(adev, out->usecase);
3203 if (uc_info == NULL) {
3204 ALOGE("%s: Could not find the usecase (%d) in the list",
3205 __func__, out->usecase);
3206 return -EINVAL;
3207 }
3208
Derek Chenea197282019-01-07 17:35:01 -08003209 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3210 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003211
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003212 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303213 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003214 if (adev->visualizer_stop_output != NULL)
3215 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003216
3217 audio_extn_dts_remove_state_notifier_node(out->usecase);
3218
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003219 if (adev->offload_effects_stop_output != NULL)
3220 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003221 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3222 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3223 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003224 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003225
Arun Mirpurief53ce52018-09-11 18:00:09 -07003226 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3227 voice_set_device_mute_flag(adev, false);
3228
Eric Laurent150dbfe2013-02-27 14:31:02 -08003229 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003230 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003231
3232 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003233 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003234
Aalique Grahame22e49102018-12-18 14:23:57 -08003235 audio_extn_extspk_update(adev->extspk);
3236
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003237 if (is_offload_usecase(out->usecase)) {
3238 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3239 adev->dsp_bit_width_enforce_mode,
3240 false);
3241 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003242 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3243 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3244 false);
3245
3246 if (ret != 0)
3247 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3248 /* default service interval was successfully updated,
3249 reopen USB backend with new service interval */
3250 ret = 0;
3251 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003252
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003253 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303254 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003255 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303256 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003257 ALOGV("Disable passthrough , reset mixer to pcm");
3258 /* NO_PASSTHROUGH */
3259 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003260 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003261 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3262 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003263
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303264 /* Must be called after removing the usecase from list */
3265 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303266 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303267
Manish Dewangan21a850a2017-08-14 12:03:55 +05303268 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003269 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3270 if (ret < 0)
3271 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3272 }
3273
juyuchen2d415992018-11-16 14:15:16 +08003274 /* 1) media + voip output routing to handset must route media back to
3275 speaker when voip stops.
3276 2) trigger voip input to reroute when voip output changes to
3277 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003278 if (has_voip_usecase ||
3279 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3280 struct listnode *node;
3281 struct audio_usecase *usecase;
3282 list_for_each(node, &adev->usecase_list) {
3283 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003284 if ((usecase->type == PCM_CAPTURE &&
3285 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3286 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003287 continue;
3288
3289 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3290 __func__, usecase->id, use_case_table[usecase->id],
3291 out->usecase, use_case_table[out->usecase]);
3292 select_devices(adev, usecase->id);
3293 }
3294 }
3295
Garmond Leung5fd0b552018-04-17 11:56:12 -07003296 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003297 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003298 return ret;
3299}
3300
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003301struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3302 unsigned int flags, unsigned int pcm_open_retry_count,
3303 struct pcm_config *config)
3304{
3305 struct pcm* pcm = NULL;
3306
3307 while (1) {
3308 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3309 if (pcm == NULL || !pcm_is_ready(pcm)) {
3310 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3311 if (pcm != NULL) {
3312 pcm_close(pcm);
3313 pcm = NULL;
3314 }
3315 if (pcm_open_retry_count-- == 0)
3316 return NULL;
3317
3318 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3319 continue;
3320 }
3321 break;
3322 }
3323
3324 if (pcm_is_ready(pcm)) {
3325 int ret = pcm_prepare(pcm);
3326 if (ret < 0) {
3327 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3328 pcm_close(pcm);
3329 pcm = NULL;
3330 }
3331 }
3332
3333 return pcm;
3334}
3335
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003336int start_output_stream(struct stream_out *out)
3337{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003338 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003339 struct audio_usecase *uc_info;
3340 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003341 char mixer_ctl_name[128];
3342 struct mixer_ctl *ctl = NULL;
3343 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303344 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003345 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003346
Haynes Mathew George380745d2017-10-04 15:27:45 -07003347 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003348 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3349 ret = -EINVAL;
3350 goto error_config;
3351 }
3352
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003353 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303354 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003355 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303356
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303357 if (CARD_STATUS_OFFLINE == out->card_status ||
3358 CARD_STATUS_OFFLINE == adev->card_status) {
3359 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303360 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303361 goto error_config;
3362 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303363
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303364 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003365 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003366 if (out->devices &
3367 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303368 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303369 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303370 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3371 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3372 ret = -EAGAIN;
3373 goto error_config;
3374 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303375 }
3376 }
3377 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303378 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3379 if (!adev->bt_sco_on) {
3380 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3381 //combo usecase just by pass a2dp
3382 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3383 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3384 } else {
3385 ALOGE("%s: SCO profile is not ready, return error", __func__);
3386 ret = -EAGAIN;
3387 goto error_config;
3388 }
3389 }
3390 }
3391
Eric Laurentb23d5282013-05-14 15:27:20 -07003392 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 if (out->pcm_device_id < 0) {
3394 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3395 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003396 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003397 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003398 }
3399
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003400 if (is_haptic_usecase) {
3401 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3402 if (adev->haptic_pcm_device_id < 0) {
3403 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3404 __func__, adev->haptic_pcm_device_id, out->usecase);
3405 ret = -EINVAL;
3406 goto error_config;
3407 }
3408 }
3409
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003410 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003411
3412 if (!uc_info) {
3413 ret = -ENOMEM;
3414 goto error_config;
3415 }
3416
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003417 uc_info->id = out->usecase;
3418 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003419 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003420 uc_info->devices = out->devices;
3421 uc_info->in_snd_device = SND_DEVICE_NONE;
3422 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003423
3424 /* This must be called before adding this usecase to the list */
3425 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3426 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3427 /* USB backend is not reopened immediately.
3428 This is eventually done as part of select_devices */
3429 }
3430
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003431 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003432
Wei Wangf7ca6c92017-11-21 14:51:20 -08003433 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303434 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3435 adev->perf_lock_opts,
3436 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303437
3438 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303439 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303440 if (audio_extn_passthru_is_enabled() &&
3441 audio_extn_passthru_is_passthrough_stream(out)) {
3442 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303443 }
3444 }
3445
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303446 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003447 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303448 if (!a2dp_combo) {
3449 check_a2dp_restore_l(adev, out, false);
3450 } else {
3451 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003452 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3453 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3454 else
3455 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303456 select_devices(adev, out->usecase);
3457 out->devices = dev;
3458 }
3459 } else {
3460 select_devices(adev, out->usecase);
3461 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003462
Arun Mirpurief53ce52018-09-11 18:00:09 -07003463 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3464 voice_set_device_mute_flag(adev, true);
3465
Derek Chenea197282019-01-07 17:35:01 -08003466 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3467 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003468
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003469 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3470 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003471
3472 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003473 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003474 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3475 ALOGE("%s: pcm stream not ready", __func__);
3476 goto error_open;
3477 }
3478 ret = pcm_start(out->pcm);
3479 if (ret < 0) {
3480 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3481 goto error_open;
3482 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003483 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003484 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003485 unsigned int flags = PCM_OUT;
3486 unsigned int pcm_open_retry_count = 0;
3487 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3488 flags |= PCM_MMAP | PCM_NOIRQ;
3489 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003490 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003491 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003492 } else
3493 flags |= PCM_MONOTONIC;
3494
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003495 if ((adev->vr_audio_mode_enabled) &&
3496 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3497 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3498 "PCM_Dev %d Topology", out->pcm_device_id);
3499 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3500 if (!ctl) {
3501 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3502 __func__, mixer_ctl_name);
3503 } else {
3504 //if success use ULLPP
3505 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3506 __func__, mixer_ctl_name, out->pcm_device_id);
3507 //There is a still a possibility that some sessions
3508 // that request for FAST|RAW when 3D audio is active
3509 //can go through ULLPP. Ideally we expects apps to
3510 //listen to audio focus and stop concurrent playback
3511 //Also, we will look for mode flag (voice_in_communication)
3512 //before enabling the realtime flag.
3513 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3514 }
3515 }
3516
Surendar Karka91fa3682018-07-02 18:12:12 +05303517 if (out->realtime)
3518 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3519 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3520
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003521 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3522 flags, pcm_open_retry_count,
3523 &(out->config));
3524 if (out->pcm == NULL) {
3525 ret = -EIO;
3526 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003527 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003528
3529 if (is_haptic_usecase) {
3530 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3531 adev->haptic_pcm_device_id,
3532 flags, pcm_open_retry_count,
3533 &(adev->haptics_config));
3534 // failure to open haptics pcm shouldnt stop audio,
3535 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003536
3537 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3538 ALOGD("%s: enable haptic audio synchronization", __func__);
3539 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3540 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003541 }
3542
Surendar Karka91fa3682018-07-02 18:12:12 +05303543 if (!out->realtime)
3544 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303545 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003546
Zhou Song2b8f28f2017-09-11 10:51:38 +08003547 // apply volume for voip playback after path is set up
3548 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3549 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303550 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3551 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303552 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3553 out->apply_volume = false;
3554 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003555 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003556 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303557 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003558 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3559 adev->dsp_bit_width_enforce_mode,
3560 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003561 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003562 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003563 out->compr = compress_open(adev->snd_card,
3564 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003565 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003566 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303567 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303568 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3569 adev->card_status = CARD_STATUS_OFFLINE;
3570 out->card_status = CARD_STATUS_OFFLINE;
3571 ret = -EIO;
3572 goto error_open;
3573 }
3574
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003575 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003576 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003577 compress_close(out->compr);
3578 out->compr = NULL;
3579 ret = -EIO;
3580 goto error_open;
3581 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303582 /* compress_open sends params of the track, so reset the flag here */
3583 out->is_compr_metadata_avail = false;
3584
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003585 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003586 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003587
Fred Oh3f43e742015-03-04 18:42:34 -08003588 /* Since small bufs uses blocking writes, a write will be blocked
3589 for the default max poll time (20s) in the event of an SSR.
3590 Reduce the poll time to observe and deal with SSR faster.
3591 */
Ashish Jain5106d362016-05-11 19:23:33 +05303592 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003593 compress_set_max_poll_wait(out->compr, 1000);
3594 }
3595
Manish Dewangan69426c82017-01-30 17:35:36 +05303596 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303597 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303598
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003599 audio_extn_dts_create_state_notifier_node(out->usecase);
3600 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3601 popcount(out->channel_mask),
3602 out->playback_started);
3603
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003604#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303605 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003606 audio_extn_dolby_send_ddp_endp_params(adev);
3607#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303608 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3609 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003610 if (adev->visualizer_start_output != NULL)
3611 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3612 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303613 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003614 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003615 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003616 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003617
3618 if (ret == 0) {
3619 register_out_stream(out);
3620 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003621 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3622 ALOGE("%s: pcm stream not ready", __func__);
3623 goto error_open;
3624 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003625 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003626 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003627 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003628 if (ret < 0)
3629 goto error_open;
3630 }
3631 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003632 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303633 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003634 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003635
vivek mehtad15d2bf2019-05-17 13:35:10 -07003636 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3637 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3638 audio_low_latency_hint_start();
3639 }
3640
Manish Dewangan21a850a2017-08-14 12:03:55 +05303641 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003642 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003643 if (ret < 0)
3644 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3645 }
3646
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003647 // consider a scenario where on pause lower layers are tear down.
3648 // so on resume, swap mixer control need to be sent only when
3649 // backend is active, hence rather than sending from enable device
3650 // sending it from start of streamtream
3651
3652 platform_set_swap_channels(adev, true);
3653
Haynes Mathew George380745d2017-10-04 15:27:45 -07003654 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303655 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003656 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003657error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003658 if (adev->haptic_pcm) {
3659 pcm_close(adev->haptic_pcm);
3660 adev->haptic_pcm = NULL;
3661 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003662 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303663 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003664 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003665error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303666 /*
3667 * sleep 50ms to allow sufficient time for kernel
3668 * drivers to recover incases like SSR.
3669 */
3670 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003671 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303672 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003673 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003674}
3675
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003676static int check_input_parameters(uint32_t sample_rate,
3677 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003678 int channel_count,
3679 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003680{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003681 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003682
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303683 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3684 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3685 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003686 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003687 !audio_extn_compr_cap_format_supported(format) &&
3688 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003689 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003690
Aalique Grahame22e49102018-12-18 14:23:57 -08003691 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3692 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3693 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3694 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3695 return -EINVAL;
3696 }
3697
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003698 switch (channel_count) {
3699 case 1:
3700 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303701 case 3:
3702 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003703 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003704 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003705 break;
3706 default:
3707 ret = -EINVAL;
3708 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003709
3710 switch (sample_rate) {
3711 case 8000:
3712 case 11025:
3713 case 12000:
3714 case 16000:
3715 case 22050:
3716 case 24000:
3717 case 32000:
3718 case 44100:
3719 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003720 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303721 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003722 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303723 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003724 break;
3725 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003726 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003727 }
3728
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003729 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003730}
3731
Naresh Tanniru04f71882018-06-26 17:46:22 +05303732
3733/** Add a value in a list if not already present.
3734 * @return true if value was successfully inserted or already present,
3735 * false if the list is full and does not contain the value.
3736 */
3737static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3738 for (size_t i = 0; i < list_length; i++) {
3739 if (list[i] == value) return true; // value is already present
3740 if (list[i] == 0) { // no values in this slot
3741 list[i] = value;
3742 return true; // value inserted
3743 }
3744 }
3745 return false; // could not insert value
3746}
3747
3748/** Add channel_mask in supported_channel_masks if not already present.
3749 * @return true if channel_mask was successfully inserted or already present,
3750 * false if supported_channel_masks is full and does not contain channel_mask.
3751 */
3752static void register_channel_mask(audio_channel_mask_t channel_mask,
3753 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3754 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3755 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3756}
3757
3758/** Add format in supported_formats if not already present.
3759 * @return true if format was successfully inserted or already present,
3760 * false if supported_formats is full and does not contain format.
3761 */
3762static void register_format(audio_format_t format,
3763 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3764 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3765 "%s: stream can not declare supporting its format %x", __func__, format);
3766}
3767/** Add sample_rate in supported_sample_rates if not already present.
3768 * @return true if sample_rate was successfully inserted or already present,
3769 * false if supported_sample_rates is full and does not contain sample_rate.
3770 */
3771static void register_sample_rate(uint32_t sample_rate,
3772 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3773 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3774 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3775}
3776
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003777static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3778{
3779 uint32_t high = num1, low = num2, temp = 0;
3780
3781 if (!num1 || !num2)
3782 return 0;
3783
3784 if (num1 < num2) {
3785 high = num2;
3786 low = num1;
3787 }
3788
3789 while (low != 0) {
3790 temp = low;
3791 low = high % low;
3792 high = temp;
3793 }
3794 return (num1 * num2)/high;
3795}
3796
3797static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3798{
3799 uint32_t remainder = 0;
3800
3801 if (!multiplier)
3802 return num;
3803
3804 remainder = num % multiplier;
3805 if (remainder)
3806 num += (multiplier - remainder);
3807
3808 return num;
3809}
3810
Aalique Grahame22e49102018-12-18 14:23:57 -08003811static size_t get_stream_buffer_size(size_t duration_ms,
3812 uint32_t sample_rate,
3813 audio_format_t format,
3814 int channel_count,
3815 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003816{
3817 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003818 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003819
Aalique Grahame22e49102018-12-18 14:23:57 -08003820 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003821 if (is_low_latency)
3822 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303823
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003824 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003825 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003826
Ralf Herzbd08d632018-09-28 15:50:49 +02003827 /* make sure the size is multiple of 32 bytes and additionally multiple of
3828 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003829 * At 48 kHz mono 16-bit PCM:
3830 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3831 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003832 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003833 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003834 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003835
3836 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003837}
3838
Aalique Grahame22e49102018-12-18 14:23:57 -08003839static size_t get_input_buffer_size(uint32_t sample_rate,
3840 audio_format_t format,
3841 int channel_count,
3842 bool is_low_latency)
3843{
3844 /* Don't know if USB HIFI in this context so use true to be conservative */
3845 if (check_input_parameters(sample_rate, format, channel_count,
3846 true /*is_usb_hifi */) != 0)
3847 return 0;
3848
3849 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3850 sample_rate,
3851 format,
3852 channel_count,
3853 is_low_latency);
3854}
3855
Derek Chenf6318be2017-06-12 17:16:24 -04003856size_t get_output_period_size(uint32_t sample_rate,
3857 audio_format_t format,
3858 int channel_count,
3859 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05303860{
3861 size_t size = 0;
3862 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3863
3864 if ((duration == 0) || (sample_rate == 0) ||
3865 (bytes_per_sample == 0) || (channel_count == 0)) {
3866 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3867 bytes_per_sample, channel_count);
3868 return -EINVAL;
3869 }
3870
3871 size = (sample_rate *
3872 duration *
3873 bytes_per_sample *
3874 channel_count) / 1000;
3875 /*
3876 * To have same PCM samples for all channels, the buffer size requires to
3877 * be multiple of (number of channels * bytes per sample)
3878 * For writes to succeed, the buffer must be written at address which is multiple of 32
3879 */
3880 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3881
3882 return (size/(channel_count * bytes_per_sample));
3883}
3884
Zhou Song48453a02018-01-10 17:50:59 +08003885static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303886{
3887 uint64_t actual_frames_rendered = 0;
3888 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3889
3890 /* This adjustment accounts for buffering after app processor.
3891 * It is based on estimated DSP latency per use case, rather than exact.
3892 */
3893 int64_t platform_latency = platform_render_latency(out->usecase) *
3894 out->sample_rate / 1000000LL;
3895
Zhou Song48453a02018-01-10 17:50:59 +08003896 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303897 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3898 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3899 * hence only estimate.
3900 */
3901 int64_t signed_frames = out->written - kernel_buffer_size;
3902
3903 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3904
Zhou Song48453a02018-01-10 17:50:59 +08003905 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303906 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003907 if (timestamp != NULL )
3908 *timestamp = out->writeAt;
3909 } else if (timestamp != NULL) {
3910 clock_gettime(CLOCK_MONOTONIC, timestamp);
3911 }
3912 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303913
3914 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3915 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3916 (long long int)out->written, (int)kernel_buffer_size,
3917 audio_bytes_per_sample(out->compr_config.codec->format),
3918 popcount(out->channel_mask));
3919
3920 return actual_frames_rendered;
3921}
3922
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3924{
3925 struct stream_out *out = (struct stream_out *)stream;
3926
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003927 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928}
3929
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003930static int out_set_sample_rate(struct audio_stream *stream __unused,
3931 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932{
3933 return -ENOSYS;
3934}
3935
3936static size_t out_get_buffer_size(const struct audio_stream *stream)
3937{
3938 struct stream_out *out = (struct stream_out *)stream;
3939
Varun Balaraje49253e2017-07-06 19:48:56 +05303940 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303941 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303942 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303943 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3944 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3945 else
3946 return out->compr_config.fragment_size;
3947 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003948 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003949 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3950 return VOIP_IO_BUF_SIZE(out->config.rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE);
Dhananjay Kumarac341582017-02-23 23:42:25 +05303951 else if (is_offload_usecase(out->usecase) &&
3952 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303953 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003954
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003955 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003956 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003957}
3958
3959static uint32_t out_get_channels(const struct audio_stream *stream)
3960{
3961 struct stream_out *out = (struct stream_out *)stream;
3962
3963 return out->channel_mask;
3964}
3965
3966static audio_format_t out_get_format(const struct audio_stream *stream)
3967{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003968 struct stream_out *out = (struct stream_out *)stream;
3969
3970 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003971}
3972
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003973static int out_set_format(struct audio_stream *stream __unused,
3974 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003975{
3976 return -ENOSYS;
3977}
3978
3979static int out_standby(struct audio_stream *stream)
3980{
3981 struct stream_out *out = (struct stream_out *)stream;
3982 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003983 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003984
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303985 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3986 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003987
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003988 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003990 if (adev->adm_deregister_stream)
3991 adev->adm_deregister_stream(adev->adm_data, out->handle);
3992
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003993 if (is_offload_usecase(out->usecase))
3994 stop_compressed_output_l(out);
3995
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003996 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003997 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003998 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3999 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304000 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004001 pthread_mutex_unlock(&adev->lock);
4002 pthread_mutex_unlock(&out->lock);
4003 ALOGD("VOIP output entered standby");
4004 return 0;
4005 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004006 if (out->pcm) {
4007 pcm_close(out->pcm);
4008 out->pcm = NULL;
4009 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004010 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4011 do_stop = out->playback_started;
4012 out->playback_started = false;
4013 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004014 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004015 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304016 out->send_next_track_params = false;
4017 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004018 out->gapless_mdata.encoder_delay = 0;
4019 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004020 if (out->compr != NULL) {
4021 compress_close(out->compr);
4022 out->compr = NULL;
4023 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004024 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004025 if (do_stop) {
4026 stop_output_stream(out);
4027 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004028 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004029 }
4030 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304031 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004032 return 0;
4033}
4034
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304035static int out_on_error(struct audio_stream *stream)
4036{
4037 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004038 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304039
4040 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004041 // always send CMD_ERROR for offload streams, this
4042 // is needed e.g. when SSR happens within compress_open
4043 // since the stream is active, offload_callback_thread is also active.
4044 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4045 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004046 }
4047 pthread_mutex_unlock(&out->lock);
4048
4049 status = out_standby(&out->stream.common);
4050
4051 lock_output_stream(out);
4052 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004053 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304054 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304055
4056 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4057 ALOGD("Setting previous card status if offline");
4058 out->prev_card_status_offline = true;
4059 }
4060
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304061 pthread_mutex_unlock(&out->lock);
4062
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004063 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304064}
4065
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304066/*
4067 *standby implementation without locks, assumes that the callee already
4068 *has taken adev and out lock.
4069 */
4070int out_standby_l(struct audio_stream *stream)
4071{
4072 struct stream_out *out = (struct stream_out *)stream;
4073 struct audio_device *adev = out->dev;
4074
4075 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4076 stream, out->usecase, use_case_table[out->usecase]);
4077
4078 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004079 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304080 if (adev->adm_deregister_stream)
4081 adev->adm_deregister_stream(adev->adm_data, out->handle);
4082
4083 if (is_offload_usecase(out->usecase))
4084 stop_compressed_output_l(out);
4085
4086 out->standby = true;
4087 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4088 voice_extn_compress_voip_close_output_stream(stream);
4089 out->started = 0;
4090 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004091 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304092 return 0;
4093 } else if (!is_offload_usecase(out->usecase)) {
4094 if (out->pcm) {
4095 pcm_close(out->pcm);
4096 out->pcm = NULL;
4097 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004098 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4099 if (adev->haptic_pcm) {
4100 pcm_close(adev->haptic_pcm);
4101 adev->haptic_pcm = NULL;
4102 }
4103
4104 if (adev->haptic_buffer != NULL) {
4105 free(adev->haptic_buffer);
4106 adev->haptic_buffer = NULL;
4107 adev->haptic_buffer_size = 0;
4108 }
4109 adev->haptic_pcm_device_id = 0;
4110 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304111 } else {
4112 ALOGD("copl(%p):standby", out);
4113 out->send_next_track_params = false;
4114 out->is_compr_metadata_avail = false;
4115 out->gapless_mdata.encoder_delay = 0;
4116 out->gapless_mdata.encoder_padding = 0;
4117 if (out->compr != NULL) {
4118 compress_close(out->compr);
4119 out->compr = NULL;
4120 }
4121 }
4122 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004123 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304124 }
4125 ALOGD("%s: exit", __func__);
4126 return 0;
4127}
4128
Aalique Grahame22e49102018-12-18 14:23:57 -08004129static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004130{
Aalique Grahame22e49102018-12-18 14:23:57 -08004131 struct stream_out *out = (struct stream_out *)stream;
4132
4133 // We try to get the lock for consistency,
4134 // but it isn't necessary for these variables.
4135 // If we're not in standby, we may be blocked on a write.
4136 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4137 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4138 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4139
4140 if (locked) {
4141 pthread_mutex_unlock(&out->lock);
4142 }
4143
4144 // dump error info
4145 (void)error_log_dump(
4146 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4147
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004148 return 0;
4149}
4150
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004151static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4152{
4153 int ret = 0;
4154 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004155
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004156 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004157 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004158 return -EINVAL;
4159 }
4160
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304161 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004162
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004163 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4164 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304165 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004166 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004167 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4168 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304169 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004170 }
4171
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004172 ALOGV("%s new encoder delay %u and padding %u", __func__,
4173 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4174
4175 return 0;
4176}
4177
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004178static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4179{
4180 return out == adev->primary_output || out == adev->voice_tx_output;
4181}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004182
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304183// note: this call is safe only if the stream_cb is
4184// removed first in close_output_stream (as is done now).
4185static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4186{
4187 if (!stream || !parms)
4188 return;
4189
4190 struct stream_out *out = (struct stream_out *)stream;
4191 struct audio_device *adev = out->dev;
4192
4193 card_status_t status;
4194 int card;
4195 if (parse_snd_card_status(parms, &card, &status) < 0)
4196 return;
4197
4198 pthread_mutex_lock(&adev->lock);
4199 bool valid_cb = (card == adev->snd_card);
4200 pthread_mutex_unlock(&adev->lock);
4201
4202 if (!valid_cb)
4203 return;
4204
4205 lock_output_stream(out);
4206 if (out->card_status != status)
4207 out->card_status = status;
4208 pthread_mutex_unlock(&out->lock);
4209
4210 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4211 use_case_table[out->usecase],
4212 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4213
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304214 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304215 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304216 if (voice_is_call_state_active(adev) &&
4217 out == adev->primary_output) {
4218 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4219 pthread_mutex_lock(&adev->lock);
4220 voice_stop_call(adev);
4221 adev->mode = AUDIO_MODE_NORMAL;
4222 pthread_mutex_unlock(&adev->lock);
4223 }
4224 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304225 return;
4226}
4227
Kevin Rocardfce19002017-08-07 19:21:36 -07004228static int get_alive_usb_card(struct str_parms* parms) {
4229 int card;
4230 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4231 !audio_extn_usb_alive(card)) {
4232 return card;
4233 }
4234 return -ENODEV;
4235}
4236
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004237static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4238{
4239 struct stream_out *out = (struct stream_out *)stream;
4240 struct audio_device *adev = out->dev;
4241 struct str_parms *parms;
4242 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004243 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304244 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004245 bool reconfig = false;
4246 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004247
sangwoobc677242013-08-08 16:53:43 +09004248 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004249 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304251 if (!parms)
4252 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004253 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4254 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004255 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004256 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004257 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004258
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004259 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004260 * When HDMI cable is unplugged the music playback is paused and
4261 * the policy manager sends routing=0. But the audioflinger continues
4262 * to write data until standby time (3sec). As the HDMI core is
4263 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004264 * Avoid this by routing audio to speaker until standby.
4265 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004266 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4267 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304268 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004269 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4270 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004271 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304272 /*
4273 * When A2DP is disconnected the
4274 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004275 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304276 * (3sec). As BT is turned off, the write gets blocked.
4277 * Avoid this by routing audio to speaker until standby.
4278 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004279 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004280 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004281 !audio_extn_a2dp_source_is_ready() &&
4282 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304283 val = AUDIO_DEVICE_OUT_SPEAKER;
4284 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304285 /*
4286 * When USB headset is disconnected the music platback paused
4287 * and the policy manager send routing=0. But if the USB is connected
4288 * back before the standby time, AFE is not closed and opened
4289 * when USB is connected back. So routing to speker will guarantee
4290 * AFE reconfiguration and AFE will be opend once USB is connected again
4291 */
4292 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4293 (val == AUDIO_DEVICE_NONE) &&
4294 !audio_extn_usb_connected(parms)) {
4295 val = AUDIO_DEVICE_OUT_SPEAKER;
4296 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304297 /* To avoid a2dp to sco overlapping / BT device improper state
4298 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304299 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304300 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004301 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004302 if (val &
4303 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304304 //combo usecase just by pass a2dp
4305 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304306 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304307 } else {
4308 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4309 /* update device to a2dp and don't route as BT returned error
4310 * However it is still possible a2dp routing called because
4311 * of current active device disconnection (like wired headset)
4312 */
4313 out->devices = val;
4314 pthread_mutex_unlock(&out->lock);
4315 pthread_mutex_unlock(&adev->lock);
4316 goto error;
4317 }
4318 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304319 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004320
4321 audio_devices_t new_dev = val;
4322
4323 // Workaround: If routing to an non existing usb device, fail gracefully
4324 // The routing request will otherwise block during 10 second
4325 int card;
4326 if (audio_is_usb_out_device(new_dev) &&
4327 (card = get_alive_usb_card(parms)) >= 0) {
4328
4329 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4330 pthread_mutex_unlock(&adev->lock);
4331 pthread_mutex_unlock(&out->lock);
4332 ret = -ENOSYS;
4333 goto routing_fail;
4334 }
4335
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004336 /*
4337 * select_devices() call below switches all the usecases on the same
4338 * backend to the new device. Refer to check_usecases_codec_backend() in
4339 * the select_devices(). But how do we undo this?
4340 *
4341 * For example, music playback is active on headset (deep-buffer usecase)
4342 * and if we go to ringtones and select a ringtone, low-latency usecase
4343 * will be started on headset+speaker. As we can't enable headset+speaker
4344 * and headset devices at the same time, select_devices() switches the music
4345 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4346 * So when the ringtone playback is completed, how do we undo the same?
4347 *
4348 * We are relying on the out_set_parameters() call on deep-buffer output,
4349 * once the ringtone playback is ended.
4350 * NOTE: We should not check if the current devices are same as new devices.
4351 * Because select_devices() must be called to switch back the music
4352 * playback to headset.
4353 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004354 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004355 audio_devices_t new_dev = val;
4356 bool same_dev = out->devices == new_dev;
4357 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004358
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004359 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004360 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004361 if (adev->mode == AUDIO_MODE_IN_CALL) {
4362 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004363 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4364 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4365 audio_extn_usb_set_service_interval(true /*playback*/,
4366 service_interval,
4367 &reconfig);
4368 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4369 }
4370 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004371 }
4372 } else {
4373 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004374 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004375 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004376 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004377
4378 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004379 if (!same_dev) {
4380 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304381 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4382 adev->perf_lock_opts,
4383 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004384 if (adev->adm_on_routing_change)
4385 adev->adm_on_routing_change(adev->adm_data,
4386 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004387 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304388 if (!bypass_a2dp) {
4389 select_devices(adev, out->usecase);
4390 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004391 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4392 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4393 else
4394 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304395 select_devices(adev, out->usecase);
4396 out->devices = new_dev;
4397 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004398
4399 if (!same_dev) {
4400 // on device switch force swap, lower functions will make sure
4401 // to check if swap is allowed or not.
4402 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304403 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004404 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304405 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4406 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004407 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304408 pthread_mutex_lock(&out->compr_mute_lock);
4409 out->a2dp_compress_mute = false;
4410 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4411 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004412 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4413 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304414 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004415 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004416 }
4417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004419 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004420
4421 /*handles device and call state changes*/
4422 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004423 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004424 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004425
4426 if (out == adev->primary_output) {
4427 pthread_mutex_lock(&adev->lock);
4428 audio_extn_set_parameters(adev, parms);
4429 pthread_mutex_unlock(&adev->lock);
4430 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004431 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004432 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004433 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004434
4435 audio_extn_dts_create_state_notifier_node(out->usecase);
4436 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4437 popcount(out->channel_mask),
4438 out->playback_started);
4439
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004440 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004441 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004442
Surendar Karkaf51b5842018-04-26 11:28:38 +05304443 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4444 sizeof(value));
4445 if (err >= 0) {
4446 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4447 audio_extn_send_dual_mono_mixing_coefficients(out);
4448 }
4449
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304450 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4451 if (err >= 0) {
4452 strlcpy(out->profile, value, sizeof(out->profile));
4453 ALOGV("updating stream profile with value '%s'", out->profile);
4454 lock_output_stream(out);
4455 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4456 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004457 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304458 out->sample_rate, out->bit_width,
4459 out->channel_mask, out->profile,
4460 &out->app_type_cfg);
4461 pthread_mutex_unlock(&out->lock);
4462 }
4463
Alexy Joseph98988832017-01-13 14:56:59 -08004464 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004465 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4466 // and vendor.audio.hal.output.suspend.supported is set to true
4467 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004468 //check suspend parameter only for low latency and if the property
4469 //is enabled
4470 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4471 ALOGI("%s: got suspend_playback %s", __func__, value);
4472 lock_output_stream(out);
4473 if (!strncmp(value, "false", 5)) {
4474 //suspend_playback=false is supposed to set QOS value back to 75%
4475 //the mixer control sent with value Enable will achieve that
4476 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4477 } else if (!strncmp (value, "true", 4)) {
4478 //suspend_playback=true is supposed to remove QOS value
4479 //resetting the mixer control will set the default value
4480 //for the mixer control which is Disable and this removes the QOS vote
4481 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4482 } else {
4483 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4484 " got %s", __func__, value);
4485 ret = -1;
4486 }
4487
4488 if (ret != 0) {
4489 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4490 __func__, out->pm_qos_mixer_path, ret);
4491 }
4492
4493 pthread_mutex_unlock(&out->lock);
4494 }
4495 }
4496 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004497 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304498error:
Eric Laurent994a6932013-07-17 11:51:42 -07004499 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004500 return ret;
4501}
4502
Paul McLeana50b7332018-12-17 08:24:21 -07004503static int in_set_microphone_direction(const struct audio_stream_in *stream,
4504 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004505 struct stream_in *in = (struct stream_in *)stream;
4506
4507 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4508
4509 in->direction = dir;
4510
4511 if (in->standby)
4512 return 0;
4513
4514 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004515}
4516
4517static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004518 struct stream_in *in = (struct stream_in *)stream;
4519
4520 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4521
4522 if (zoom > 1.0 || zoom < -1.0)
4523 return -EINVAL;
4524
4525 in->zoom = zoom;
4526
4527 if (in->standby)
4528 return 0;
4529
4530 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004531}
4532
4533
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004534static bool stream_get_parameter_channels(struct str_parms *query,
4535 struct str_parms *reply,
4536 audio_channel_mask_t *supported_channel_masks) {
4537 int ret = -1;
4538 char value[512];
4539 bool first = true;
4540 size_t i, j;
4541
4542 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4543 ret = 0;
4544 value[0] = '\0';
4545 i = 0;
4546 while (supported_channel_masks[i] != 0) {
4547 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4548 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4549 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304550 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004551
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304552 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004553 first = false;
4554 break;
4555 }
4556 }
4557 i++;
4558 }
4559 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4560 }
4561 return ret == 0;
4562}
4563
4564static bool stream_get_parameter_formats(struct str_parms *query,
4565 struct str_parms *reply,
4566 audio_format_t *supported_formats) {
4567 int ret = -1;
4568 char value[256];
4569 size_t i, j;
4570 bool first = true;
4571
4572 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4573 ret = 0;
4574 value[0] = '\0';
4575 i = 0;
4576 while (supported_formats[i] != 0) {
4577 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4578 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4579 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304580 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004581 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304582 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004583 first = false;
4584 break;
4585 }
4586 }
4587 i++;
4588 }
4589 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4590 }
4591 return ret == 0;
4592}
4593
4594static bool stream_get_parameter_rates(struct str_parms *query,
4595 struct str_parms *reply,
4596 uint32_t *supported_sample_rates) {
4597
4598 int i;
4599 char value[256];
4600 int ret = -1;
4601 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4602 ret = 0;
4603 value[0] = '\0';
4604 i=0;
4605 int cursor = 0;
4606 while (supported_sample_rates[i]) {
4607 int avail = sizeof(value) - cursor;
4608 ret = snprintf(value + cursor, avail, "%s%d",
4609 cursor > 0 ? "|" : "",
4610 supported_sample_rates[i]);
4611 if (ret < 0 || ret >= avail) {
4612 // if cursor is at the last element of the array
4613 // overwrite with \0 is duplicate work as
4614 // snprintf already put a \0 in place.
4615 // else
4616 // we had space to write the '|' at value[cursor]
4617 // (which will be overwritten) or no space to fill
4618 // the first element (=> cursor == 0)
4619 value[cursor] = '\0';
4620 break;
4621 }
4622 cursor += ret;
4623 ++i;
4624 }
4625 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4626 value);
4627 }
4628 return ret >= 0;
4629}
4630
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4632{
4633 struct stream_out *out = (struct stream_out *)stream;
4634 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004635 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004636 char value[256];
4637 struct str_parms *reply = str_parms_create();
4638 size_t i, j;
4639 int ret;
4640 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004641
4642 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004643 if (reply) {
4644 str_parms_destroy(reply);
4645 }
4646 if (query) {
4647 str_parms_destroy(query);
4648 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004649 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4650 return NULL;
4651 }
4652
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004653 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004654 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4655 if (ret >= 0) {
4656 value[0] = '\0';
4657 i = 0;
4658 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004659 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4660 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004661 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004662 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004663 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004664 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004665 first = false;
4666 break;
4667 }
4668 }
4669 i++;
4670 }
4671 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4672 str = str_parms_to_str(reply);
4673 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004674 voice_extn_out_get_parameters(out, query, reply);
4675 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004676 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004677
Alexy Joseph62142aa2015-11-16 15:10:34 -08004678
4679 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4680 if (ret >= 0) {
4681 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304682 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4683 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004684 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304685 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004686 } else {
4687 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304688 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004689 }
4690 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004691 if (str)
4692 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004693 str = str_parms_to_str(reply);
4694 }
4695
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004696 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4697 if (ret >= 0) {
4698 value[0] = '\0';
4699 i = 0;
4700 first = true;
4701 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004702 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4703 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004704 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004705 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004706 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004707 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004708 first = false;
4709 break;
4710 }
4711 }
4712 i++;
4713 }
4714 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004715 if (str)
4716 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004717 str = str_parms_to_str(reply);
4718 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004719
4720 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4721 if (ret >= 0) {
4722 value[0] = '\0';
4723 i = 0;
4724 first = true;
4725 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004726 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4727 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004728 if (!first) {
4729 strlcat(value, "|", sizeof(value));
4730 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004731 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004732 first = false;
4733 break;
4734 }
4735 }
4736 i++;
4737 }
4738 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4739 if (str)
4740 free(str);
4741 str = str_parms_to_str(reply);
4742 }
4743
Alexy Joseph98988832017-01-13 14:56:59 -08004744 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4745 //only low latency track supports suspend_resume
4746 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004747 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004748 if (str)
4749 free(str);
4750 str = str_parms_to_str(reply);
4751 }
4752
4753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004754 str_parms_destroy(query);
4755 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004756 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004757 return str;
4758}
4759
4760static uint32_t out_get_latency(const struct audio_stream_out *stream)
4761{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004762 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004764 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004765
Alexy Josephaa54c872014-12-03 02:46:47 -08004766 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304767 lock_output_stream(out);
4768 latency = audio_extn_utils_compress_get_dsp_latency(out);
4769 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004770 } else if ((out->realtime) ||
4771 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004772 // since the buffer won't be filled up faster than realtime,
4773 // return a smaller number
4774 if (out->config.rate)
4775 period_ms = (out->af_period_multiplier * out->config.period_size *
4776 1000) / (out->config.rate);
4777 else
4778 period_ms = 0;
4779 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004780 } else {
4781 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004782 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004783 }
4784
yidongh0515e042017-07-06 15:00:34 +08004785 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004786 latency += audio_extn_a2dp_get_encoder_latency();
4787
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304788 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004789 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004790}
4791
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304792static float AmpToDb(float amplification)
4793{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304794 float db = DSD_VOLUME_MIN_DB;
4795 if (amplification > 0) {
4796 db = 20 * log10(amplification);
4797 if(db < DSD_VOLUME_MIN_DB)
4798 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304799 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304800 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304801}
4802
Arun Mirpuri5d170872019-03-26 13:21:31 -07004803static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4804 float right)
4805{
4806 struct stream_out *out = (struct stream_out *)stream;
4807 long volume = 0;
4808 char mixer_ctl_name[128] = "";
4809 struct audio_device *adev = out->dev;
4810 struct mixer_ctl *ctl = NULL;
4811 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4812 PCM_PLAYBACK);
4813
4814 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4815 "Playback %d Volume", pcm_device_id);
4816 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4817 if (!ctl) {
4818 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4819 __func__, mixer_ctl_name);
4820 return -EINVAL;
4821 }
4822 if (left != right)
4823 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4824 __func__, left, right);
4825 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4826 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4827 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4828 __func__, mixer_ctl_name, volume);
4829 return -EINVAL;
4830 }
4831 return 0;
4832}
4833
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304834static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4835 float right)
4836{
4837 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304838 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304839 char mixer_ctl_name[128];
4840 struct audio_device *adev = out->dev;
4841 struct mixer_ctl *ctl;
4842 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4843 PCM_PLAYBACK);
4844
4845 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4846 "Compress Playback %d Volume", pcm_device_id);
4847 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4848 if (!ctl) {
4849 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4850 __func__, mixer_ctl_name);
4851 return -EINVAL;
4852 }
4853 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4854 __func__, mixer_ctl_name, left, right);
4855 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4856 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4857 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4858
4859 return 0;
4860}
4861
Zhou Song2b8f28f2017-09-11 10:51:38 +08004862static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4863 float right)
4864{
4865 struct stream_out *out = (struct stream_out *)stream;
4866 char mixer_ctl_name[] = "App Type Gain";
4867 struct audio_device *adev = out->dev;
4868 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304869 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004870
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07004871 if (!is_valid_volume(left, right)) {
4872 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
4873 __func__, left, right);
4874 return -EINVAL;
4875 }
4876
Zhou Song2b8f28f2017-09-11 10:51:38 +08004877 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4878 if (!ctl) {
4879 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4880 __func__, mixer_ctl_name);
4881 return -EINVAL;
4882 }
4883
4884 set_values[0] = 0; //0: Rx Session 1:Tx Session
4885 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304886 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4887 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004888
4889 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4890 return 0;
4891}
4892
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304893static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4894 float right)
4895{
4896 struct stream_out *out = (struct stream_out *)stream;
4897 /* Volume control for pcm playback */
4898 if (left != right) {
4899 return -EINVAL;
4900 } else {
4901 char mixer_ctl_name[128];
4902 struct audio_device *adev = out->dev;
4903 struct mixer_ctl *ctl;
4904 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4905 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4906 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4907 if (!ctl) {
4908 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4909 return -EINVAL;
4910 }
4911
4912 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4913 int ret = mixer_ctl_set_value(ctl, 0, volume);
4914 if (ret < 0) {
4915 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4916 return -EINVAL;
4917 }
4918
4919 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4920
4921 return 0;
4922 }
4923}
4924
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004925static int out_set_volume(struct audio_stream_out *stream, float left,
4926 float right)
4927{
Eric Laurenta9024de2013-04-04 09:19:12 -07004928 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004929 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304930 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004931
Arun Mirpuri5d170872019-03-26 13:21:31 -07004932 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07004933 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4934 /* only take left channel into account: the API is for stereo anyway */
4935 out->muted = (left == 0.0f);
4936 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004937 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304938 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004939 /*
4940 * Set mute or umute on HDMI passthrough stream.
4941 * Only take left channel into account.
4942 * Mute is 0 and unmute 1
4943 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304944 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304945 } else if (out->format == AUDIO_FORMAT_DSD){
4946 char mixer_ctl_name[128] = "DSD Volume";
4947 struct audio_device *adev = out->dev;
4948 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4949
4950 if (!ctl) {
4951 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4952 __func__, mixer_ctl_name);
4953 return -EINVAL;
4954 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304955 volume[0] = (long)(AmpToDb(left));
4956 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304957 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4958 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004959 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304960 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07004961 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304962 if (!out->a2dp_compress_mute)
4963 ret = out_set_compr_volume(stream, left, right);
4964 out->volume_l = left;
4965 out->volume_r = right;
4966 pthread_mutex_unlock(&out->compr_mute_lock);
4967 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004968 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004969 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004970 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4971 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4972 if (!out->standby) {
4973 audio_extn_utils_send_app_type_gain(out->dev,
4974 out->app_type_cfg.app_type,
4975 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004976 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004977 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004978 out->volume_l = left;
4979 out->volume_r = right;
4980 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07004981 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4982 ALOGV("%s: MMAP set volume called", __func__);
4983 if (!out->standby)
4984 ret = out_set_mmap_volume(stream, left, right);
4985 out->volume_l = left;
4986 out->volume_r = right;
4987 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304988 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304989 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4990 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304991 /* Volume control for pcm playback */
4992 if (!out->standby)
4993 ret = out_set_pcm_volume(stream, left, right);
4994 else
4995 out->apply_volume = true;
4996
4997 out->volume_l = left;
4998 out->volume_r = right;
4999 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005000 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005001
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005002 return -ENOSYS;
5003}
5004
Zhou Songc9672822017-08-16 16:01:39 +08005005static void update_frames_written(struct stream_out *out, size_t bytes)
5006{
5007 size_t bpf = 0;
5008
5009 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5010 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5011 bpf = 1;
5012 else if (!is_offload_usecase(out->usecase))
5013 bpf = audio_bytes_per_sample(out->format) *
5014 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005015
5016 pthread_mutex_lock(&out->position_query_lock);
5017 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005018 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005019 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5020 }
5021 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005022}
5023
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005024int split_and_write_audio_haptic_data(struct stream_out *out,
5025 const void *buffer, size_t bytes_to_write)
5026{
5027 struct audio_device *adev = out->dev;
5028
5029 int ret = 0;
5030 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5031 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5032 size_t frame_size = channel_count * bytes_per_sample;
5033 size_t frame_count = bytes_to_write / frame_size;
5034
5035 bool force_haptic_path =
5036 property_get_bool("vendor.audio.test_haptic", false);
5037
5038 // extract Haptics data from Audio buffer
5039 bool alloc_haptic_buffer = false;
5040 int haptic_channel_count = adev->haptics_config.channels;
5041 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5042 size_t audio_frame_size = frame_size - haptic_frame_size;
5043 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5044
5045 if (adev->haptic_buffer == NULL) {
5046 alloc_haptic_buffer = true;
5047 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5048 free(adev->haptic_buffer);
5049 adev->haptic_buffer_size = 0;
5050 alloc_haptic_buffer = true;
5051 }
5052
5053 if (alloc_haptic_buffer) {
5054 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005055 if(adev->haptic_buffer == NULL) {
5056 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5057 return -ENOMEM;
5058 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005059 adev->haptic_buffer_size = total_haptic_buffer_size;
5060 }
5061
5062 size_t src_index = 0, aud_index = 0, hap_index = 0;
5063 uint8_t *audio_buffer = (uint8_t *)buffer;
5064 uint8_t *haptic_buffer = adev->haptic_buffer;
5065
5066 // This is required for testing only. This works for stereo data only.
5067 // One channel is fed to audio stream and other to haptic stream for testing.
5068 if (force_haptic_path)
5069 audio_frame_size = haptic_frame_size = bytes_per_sample;
5070
5071 for (size_t i = 0; i < frame_count; i++) {
5072 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5073 audio_frame_size);
5074 aud_index += audio_frame_size;
5075 src_index += audio_frame_size;
5076
5077 if (adev->haptic_pcm)
5078 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5079 haptic_frame_size);
5080 hap_index += haptic_frame_size;
5081 src_index += haptic_frame_size;
5082
5083 // This is required for testing only.
5084 // Discard haptic channel data.
5085 if (force_haptic_path)
5086 src_index += haptic_frame_size;
5087 }
5088
5089 // write to audio pipeline
5090 ret = pcm_write(out->pcm, (void *)audio_buffer,
5091 frame_count * audio_frame_size);
5092
5093 // write to haptics pipeline
5094 if (adev->haptic_pcm)
5095 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5096 frame_count * haptic_frame_size);
5097
5098 return ret;
5099}
5100
Aalique Grahame22e49102018-12-18 14:23:57 -08005101#ifdef NO_AUDIO_OUT
5102static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5103 const void *buffer __unused, size_t bytes)
5104{
5105 struct stream_out *out = (struct stream_out *)stream;
5106
5107 /* No Output device supported other than BT for playback.
5108 * Sleep for the amount of buffer duration
5109 */
5110 lock_output_stream(out);
5111 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5112 (const struct audio_stream_out *)&out->stream) /
5113 out_get_sample_rate(&out->stream.common));
5114 pthread_mutex_unlock(&out->lock);
5115 return bytes;
5116}
5117#endif
5118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005119static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5120 size_t bytes)
5121{
5122 struct stream_out *out = (struct stream_out *)stream;
5123 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005124 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305125 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005126 const size_t frame_size = audio_stream_out_frame_size(stream);
5127 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305128 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005129
Haynes Mathew George380745d2017-10-04 15:27:45 -07005130 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005131 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305132
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305133 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005134
Dhananjay Kumarac341582017-02-23 23:42:25 +05305135 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305136 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305137 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5138 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005139 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305140 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305141 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305142 ALOGD(" %s: sound card is not active/SSR state", __func__);
5143 ret= -EIO;
5144 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305145 }
5146 }
5147
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305148 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305149 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305150 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305151 goto exit;
5152 }
5153
Haynes Mathew George16081042017-05-31 17:16:49 -07005154 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5155 ret = -EINVAL;
5156 goto exit;
5157 }
5158
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305159 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5160 !out->is_iec61937_info_available) {
5161
5162 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5163 out->is_iec61937_info_available = true;
5164 } else if (audio_extn_passthru_is_enabled()) {
5165 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305166 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305167
5168 if((out->format == AUDIO_FORMAT_DTS) ||
5169 (out->format == AUDIO_FORMAT_DTS_HD)) {
5170 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5171 buffer, bytes);
5172 if (ret) {
5173 if (ret != -ENOSYS) {
5174 out->is_iec61937_info_available = false;
5175 ALOGD("iec61937 transmission info not yet updated retry");
5176 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305177 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305178 /* if stream has started and after that there is
5179 * stream config change (iec transmission config)
5180 * then trigger select_device to update backend configuration.
5181 */
5182 out->stream_config_changed = true;
5183 pthread_mutex_lock(&adev->lock);
5184 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305185 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005186 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305187 ret = -EINVAL;
5188 goto exit;
5189 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305190 pthread_mutex_unlock(&adev->lock);
5191 out->stream_config_changed = false;
5192 out->is_iec61937_info_available = true;
5193 }
5194 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305195
Garmond Leung317cbf12017-09-13 16:20:50 -07005196 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305197 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5198 (out->is_iec61937_info_available == true)) {
5199 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5200 ret = -EINVAL;
5201 goto exit;
5202 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305203 }
5204 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305205
5206 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005207 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005208 if (!(out->devices &
5209 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305210 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305211 ret = -EIO;
5212 goto exit;
5213 }
5214 }
5215 }
5216
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005217 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005218 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005219 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005220 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5221 ret = voice_extn_compress_voip_start_output_stream(out);
5222 else
5223 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005224 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005225 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005226 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005227 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005228 goto exit;
5229 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305230 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005231 if (last_known_cal_step != -1) {
5232 ALOGD("%s: retry previous failed cal level set", __func__);
5233 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305234 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005235 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305236
5237 if ((out->is_iec61937_info_available == true) &&
5238 (audio_extn_passthru_is_passthrough_stream(out))&&
5239 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5240 ret = -EINVAL;
5241 goto exit;
5242 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305243 if (out->set_dual_mono)
5244 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005245 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005246
Ashish Jain81eb2a82015-05-13 10:52:34 +05305247 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005248 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305249 adev->is_channel_status_set = true;
5250 }
5251
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305252 if ((adev->use_old_pspd_mix_ctrl == true) &&
5253 (out->pspd_coeff_sent == false)) {
5254 /*
5255 * Need to resend pspd coefficients after stream started for
5256 * older kernel version as it does not save the coefficients
5257 * and also stream has to be started for coeff to apply.
5258 */
5259 usecase = get_usecase_from_list(adev, out->usecase);
5260 if (usecase != NULL) {
5261 audio_extn_set_custom_mtmx_params(adev, usecase, true);
5262 out->pspd_coeff_sent = true;
5263 }
5264 }
5265
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005266 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005267 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005268 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005269 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005270 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5271 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305272 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5273 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005274 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305275 out->send_next_track_params = false;
5276 out->is_compr_metadata_avail = false;
5277 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005278 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305279 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305280 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005281
Ashish Jain83a6cc22016-06-28 14:34:17 +05305282 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305283 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305284 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305285 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005286 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305287 return -EINVAL;
5288 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305289 audio_format_t dst_format = out->hal_op_format;
5290 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305291
Dieter Luecking5d57def2018-09-07 14:23:37 +02005292 /* prevent division-by-zero */
5293 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5294 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5295 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5296 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305297 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005298 ATRACE_END();
5299 return -EINVAL;
5300 }
5301
Ashish Jainf1eaa582016-05-23 20:54:24 +05305302 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5303 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5304
Ashish Jain83a6cc22016-06-28 14:34:17 +05305305 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305306 dst_format,
5307 buffer,
5308 src_format,
5309 frames);
5310
Ashish Jain83a6cc22016-06-28 14:34:17 +05305311 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305312 bytes_to_write);
5313
5314 /*Convert written bytes in audio flinger format*/
5315 if (ret > 0)
5316 ret = ((ret * format_to_bitwidth_table[out->format]) /
5317 format_to_bitwidth_table[dst_format]);
5318 }
5319 } else
5320 ret = compress_write(out->compr, buffer, bytes);
5321
Zhou Songc9672822017-08-16 16:01:39 +08005322 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5323 update_frames_written(out, bytes);
5324
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305325 if (ret < 0)
5326 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005327 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305328 /*msg to cb thread only if non blocking write is enabled*/
5329 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305330 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005331 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305332 } else if (-ENETRESET == ret) {
5333 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305334 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305335 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305336 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005337 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305338 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005339 }
Ashish Jain5106d362016-05-11 19:23:33 +05305340
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305341 /* Call compr start only when non-zero bytes of data is there to be rendered */
5342 if (!out->playback_started && ret > 0) {
5343 int status = compress_start(out->compr);
5344 if (status < 0) {
5345 ret = status;
5346 ALOGE("%s: compr start failed with err %d", __func__, errno);
5347 goto exit;
5348 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005349 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005350 out->playback_started = 1;
5351 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005352
5353 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5354 popcount(out->channel_mask),
5355 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005356 }
5357 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005358 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005359 return ret;
5360 } else {
5361 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005362 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005363 if (out->muted)
5364 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005365 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5366 __func__, frames, frame_size, bytes_to_write);
5367
Aalique Grahame22e49102018-12-18 14:23:57 -08005368 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005369 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5370 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5371 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005372 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5373 int16_t *src = (int16_t *)buffer;
5374 int16_t *dst = (int16_t *)buffer;
5375
5376 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5377 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005378 "out_write called for %s use case with wrong properties",
5379 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005380
5381 /*
5382 * FIXME: this can be removed once audio flinger mixer supports
5383 * mono output
5384 */
5385
5386 /*
5387 * Code below goes over each frame in the buffer and adds both
5388 * L and R samples and then divides by 2 to convert to mono
5389 */
5390 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5391 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5392 }
5393 bytes_to_write /= 2;
5394 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005395
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305396 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005397
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005398 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005399
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005400 if (out->config.rate)
5401 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5402 out->config.rate;
5403
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005404 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005405 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5406
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005407 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005408 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005409 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305410 out->convert_buffer != NULL) {
5411
5412 memcpy_by_audio_format(out->convert_buffer,
5413 out->hal_op_format,
5414 buffer,
5415 out->hal_ip_format,
5416 out->config.period_size * out->config.channels);
5417
5418 ret = pcm_write(out->pcm, out->convert_buffer,
5419 (out->config.period_size *
5420 out->config.channels *
5421 format_to_bitwidth_table[out->hal_op_format]));
5422 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305423 /*
5424 * To avoid underrun in DSP when the application is not pumping
5425 * data at required rate, check for the no. of bytes and ignore
5426 * pcm_write if it is less than actual buffer size.
5427 * It is a work around to a change in compress VOIP driver.
5428 */
5429 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5430 bytes < (out->config.period_size * out->config.channels *
5431 audio_bytes_per_sample(out->format))) {
5432 size_t voip_buf_size =
5433 out->config.period_size * out->config.channels *
5434 audio_bytes_per_sample(out->format);
5435 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5436 __func__, bytes, voip_buf_size);
5437 usleep(((uint64_t)voip_buf_size - bytes) *
5438 1000000 / audio_stream_out_frame_size(stream) /
5439 out_get_sample_rate(&out->stream.common));
5440 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005441 } else {
5442 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5443 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5444 else
5445 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5446 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305447 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005448
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005449 release_out_focus(out);
5450
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305451 if (ret < 0)
5452 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005453 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305454 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005455 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005456 }
5457
5458exit:
Zhou Songc9672822017-08-16 16:01:39 +08005459 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305460 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305461 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305462 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005463 pthread_mutex_unlock(&out->lock);
5464
5465 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005466 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005467 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305468 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305469 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305470 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305471 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305472 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305473 out->standby = true;
5474 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305475 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005476 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5477 /* prevent division-by-zero */
5478 uint32_t stream_size = audio_stream_out_frame_size(stream);
5479 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005480
Dieter Luecking5d57def2018-09-07 14:23:37 +02005481 if ((stream_size == 0) || (srate == 0)) {
5482 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5483 ATRACE_END();
5484 return -EINVAL;
5485 }
5486 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5487 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005488 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305489 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005490 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005491 return ret;
5492 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005493 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005494 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005495 return bytes;
5496}
5497
5498static int out_get_render_position(const struct audio_stream_out *stream,
5499 uint32_t *dsp_frames)
5500{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005501 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005502
5503 if (dsp_frames == NULL)
5504 return -EINVAL;
5505
5506 *dsp_frames = 0;
5507 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005508 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305509
5510 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5511 * this operation and adev_close_output_stream(where out gets reset).
5512 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305513 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005514 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305515 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005516 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305517 return 0;
5518 }
5519
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005520 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305521 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305522 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005523 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305524 if (ret < 0)
5525 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005526 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305527 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005528 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305529 if (-ENETRESET == ret) {
5530 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305531 out->card_status = CARD_STATUS_OFFLINE;
5532 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305533 } else if(ret < 0) {
5534 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305535 ret = -EINVAL;
5536 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305537 /*
5538 * Handle corner case where compress session is closed during SSR
5539 * and timestamp is queried
5540 */
5541 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305542 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305543 } else if (out->prev_card_status_offline) {
5544 ALOGE("ERROR: previously sound card was offline,return error");
5545 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305546 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305547 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005548 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305549 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305550 pthread_mutex_unlock(&out->lock);
5551 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005552 } else if (audio_is_linear_pcm(out->format)) {
5553 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005554 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005555 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005556 } else
5557 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005558}
5559
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005560static int out_add_audio_effect(const struct audio_stream *stream __unused,
5561 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005562{
5563 return 0;
5564}
5565
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005566static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5567 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005568{
5569 return 0;
5570}
5571
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005572static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5573 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005574{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305575 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005576}
5577
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005578static int out_get_presentation_position(const struct audio_stream_out *stream,
5579 uint64_t *frames, struct timespec *timestamp)
5580{
5581 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305582 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005583 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005584
Ashish Jain5106d362016-05-11 19:23:33 +05305585 /* below piece of code is not guarded against any lock because audioFliner serializes
5586 * this operation and adev_close_output_stream( where out gets reset).
5587 */
5588 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305589 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005590 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305591 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5592 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5593 return 0;
5594 }
5595
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005596 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005597
Ashish Jain5106d362016-05-11 19:23:33 +05305598 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5599 ret = compress_get_tstamp(out->compr, &dsp_frames,
5600 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005601 // Adjustment accounts for A2dp encoder latency with offload usecases
5602 // Note: Encoder latency is returned in ms.
5603 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5604 unsigned long offset =
5605 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5606 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5607 }
Ashish Jain5106d362016-05-11 19:23:33 +05305608 ALOGVV("%s rendered frames %ld sample_rate %d",
5609 __func__, dsp_frames, out->sample_rate);
5610 *frames = dsp_frames;
5611 if (ret < 0)
5612 ret = -errno;
5613 if (-ENETRESET == ret) {
5614 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305615 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305616 ret = -EINVAL;
5617 } else
5618 ret = 0;
5619 /* this is the best we can do */
5620 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005621 } else {
5622 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005623 unsigned int avail;
5624 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5625 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5626 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5627 // This adjustment accounts for buffering after app processor.
5628 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005629 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005630 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005631
Weiyin Jiangd4633762018-03-16 12:05:03 +08005632 // Adjustment accounts for A2dp encoder latency with non offload usecases
5633 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5634 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5635 signed_frames -=
5636 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5637 }
5638
5639 // It would be unusual for this value to be negative, but check just in case ...
5640 if (signed_frames >= 0) {
5641 *frames = signed_frames;
5642 ret = 0;
5643 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005644 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305645 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305646 *frames = out->written;
5647 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305648 if (is_offload_usecase(out->usecase))
5649 ret = -EINVAL;
5650 else
5651 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005652 }
5653 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005654 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005655 return ret;
5656}
5657
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005658static int out_set_callback(struct audio_stream_out *stream,
5659 stream_callback_t callback, void *cookie)
5660{
5661 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005662 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005663
5664 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005665 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005666 out->client_callback = callback;
5667 out->client_cookie = cookie;
5668 if (out->adsp_hdlr_stream_handle) {
5669 ret = audio_extn_adsp_hdlr_stream_set_callback(
5670 out->adsp_hdlr_stream_handle,
5671 callback,
5672 cookie);
5673 if (ret)
5674 ALOGW("%s:adsp hdlr callback registration failed %d",
5675 __func__, ret);
5676 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005677 pthread_mutex_unlock(&out->lock);
5678 return 0;
5679}
5680
5681static int out_pause(struct audio_stream_out* stream)
5682{
5683 struct stream_out *out = (struct stream_out *)stream;
5684 int status = -ENOSYS;
5685 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005686 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005687 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005688 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005689 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305690 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305691 status = compress_pause(out->compr);
5692
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005693 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005694
Mingming Yin21854652016-04-13 11:54:02 -07005695 if (audio_extn_passthru_is_active()) {
5696 ALOGV("offload use case, pause passthru");
5697 audio_extn_passthru_on_pause(out);
5698 }
5699
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305700 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005701 audio_extn_dts_notify_playback_state(out->usecase, 0,
5702 out->sample_rate, popcount(out->channel_mask),
5703 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005704 }
5705 pthread_mutex_unlock(&out->lock);
5706 }
5707 return status;
5708}
5709
5710static int out_resume(struct audio_stream_out* stream)
5711{
5712 struct stream_out *out = (struct stream_out *)stream;
5713 int status = -ENOSYS;
5714 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005715 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005716 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005717 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005718 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005719 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305720 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305721 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005722 }
5723 if (!status) {
5724 out->offload_state = OFFLOAD_STATE_PLAYING;
5725 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305726 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005727 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5728 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005729 }
5730 pthread_mutex_unlock(&out->lock);
5731 }
5732 return status;
5733}
5734
5735static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5736{
5737 struct stream_out *out = (struct stream_out *)stream;
5738 int status = -ENOSYS;
5739 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005740 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005741 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005742 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5743 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5744 else
5745 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5746 pthread_mutex_unlock(&out->lock);
5747 }
5748 return status;
5749}
5750
5751static int out_flush(struct audio_stream_out* stream)
5752{
5753 struct stream_out *out = (struct stream_out *)stream;
5754 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005755 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005756 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005757 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005758 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5759 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005760 } else {
5761 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5762 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005763 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005764 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005765 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005766 return 0;
5767 }
5768 return -ENOSYS;
5769}
5770
Haynes Mathew George16081042017-05-31 17:16:49 -07005771static int out_stop(const struct audio_stream_out* stream)
5772{
5773 struct stream_out *out = (struct stream_out *)stream;
5774 struct audio_device *adev = out->dev;
5775 int ret = -ENOSYS;
5776
5777 ALOGV("%s", __func__);
5778 pthread_mutex_lock(&adev->lock);
5779 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5780 out->playback_started && out->pcm != NULL) {
5781 pcm_stop(out->pcm);
5782 ret = stop_output_stream(out);
5783 out->playback_started = false;
5784 }
5785 pthread_mutex_unlock(&adev->lock);
5786 return ret;
5787}
5788
5789static int out_start(const struct audio_stream_out* stream)
5790{
5791 struct stream_out *out = (struct stream_out *)stream;
5792 struct audio_device *adev = out->dev;
5793 int ret = -ENOSYS;
5794
5795 ALOGV("%s", __func__);
5796 pthread_mutex_lock(&adev->lock);
5797 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5798 !out->playback_started && out->pcm != NULL) {
5799 ret = start_output_stream(out);
5800 if (ret == 0) {
5801 out->playback_started = true;
5802 }
5803 }
5804 pthread_mutex_unlock(&adev->lock);
5805 return ret;
5806}
5807
5808/*
5809 * Modify config->period_count based on min_size_frames
5810 */
5811static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5812{
5813 int periodCountRequested = (min_size_frames + config->period_size - 1)
5814 / config->period_size;
5815 int periodCount = MMAP_PERIOD_COUNT_MIN;
5816
5817 ALOGV("%s original config.period_size = %d config.period_count = %d",
5818 __func__, config->period_size, config->period_count);
5819
5820 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5821 periodCount *= 2;
5822 }
5823 config->period_count = periodCount;
5824
5825 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5826}
5827
Phil Burkfe17efd2019-03-25 10:23:35 -07005828// Read offset for the positional timestamp from a persistent vendor property.
5829// This is to workaround apparent inaccuracies in the timing information that
5830// is used by the AAudio timing model. The inaccuracies can cause glitches.
5831static int64_t get_mmap_out_time_offset() {
5832 const int32_t kDefaultOffsetMicros = 0;
5833 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08005834 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07005835 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
5836 return mmap_time_offset_micros * (int64_t)1000;
5837}
5838
Haynes Mathew George16081042017-05-31 17:16:49 -07005839static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5840 int32_t min_size_frames,
5841 struct audio_mmap_buffer_info *info)
5842{
5843 struct stream_out *out = (struct stream_out *)stream;
5844 struct audio_device *adev = out->dev;
5845 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005846 unsigned int offset1 = 0;
5847 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005848 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005849 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005850 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005851
Arun Mirpuri5d170872019-03-26 13:21:31 -07005852 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305853 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005854 pthread_mutex_lock(&adev->lock);
5855
Sharad Sanglec6f32552018-05-04 16:15:38 +05305856 if (CARD_STATUS_OFFLINE == out->card_status ||
5857 CARD_STATUS_OFFLINE == adev->card_status) {
5858 ALOGW("out->card_status or adev->card_status offline, try again");
5859 ret = -EIO;
5860 goto exit;
5861 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005862 if (info == NULL || min_size_frames == 0) {
5863 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5864 ret = -EINVAL;
5865 goto exit;
5866 }
5867 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5868 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5869 ret = -ENOSYS;
5870 goto exit;
5871 }
5872 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5873 if (out->pcm_device_id < 0) {
5874 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5875 __func__, out->pcm_device_id, out->usecase);
5876 ret = -EINVAL;
5877 goto exit;
5878 }
5879
5880 adjust_mmap_period_count(&out->config, min_size_frames);
5881
Arun Mirpuri5d170872019-03-26 13:21:31 -07005882 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005883 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5884 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5885 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305886 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305887 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5888 out->card_status = CARD_STATUS_OFFLINE;
5889 adev->card_status = CARD_STATUS_OFFLINE;
5890 ret = -EIO;
5891 goto exit;
5892 }
5893
Haynes Mathew George16081042017-05-31 17:16:49 -07005894 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5895 step = "open";
5896 ret = -ENODEV;
5897 goto exit;
5898 }
5899 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5900 if (ret < 0) {
5901 step = "begin";
5902 goto exit;
5903 }
5904 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005905 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005906 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005907 ret = platform_get_mmap_data_fd(adev->platform,
5908 out->pcm_device_id, 0 /*playback*/,
5909 &info->shared_memory_fd,
5910 &mmap_size);
5911 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005912 // Fall back to non exclusive mode
5913 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5914 } else {
5915 if (mmap_size < buffer_size) {
5916 step = "mmap";
5917 goto exit;
5918 }
5919 // FIXME: indicate exclusive mode support by returning a negative buffer size
5920 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005921 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005922 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005923 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005924
5925 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5926 if (ret < 0) {
5927 step = "commit";
5928 goto exit;
5929 }
5930
Phil Burkfe17efd2019-03-25 10:23:35 -07005931 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
5932
Haynes Mathew George16081042017-05-31 17:16:49 -07005933 out->standby = false;
5934 ret = 0;
5935
Arun Mirpuri5d170872019-03-26 13:21:31 -07005936 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005937 __func__, info->shared_memory_address, info->buffer_size_frames);
5938
5939exit:
5940 if (ret != 0) {
5941 if (out->pcm == NULL) {
5942 ALOGE("%s: %s - %d", __func__, step, ret);
5943 } else {
5944 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5945 pcm_close(out->pcm);
5946 out->pcm = NULL;
5947 }
5948 }
5949 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305950 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005951 return ret;
5952}
5953
5954static int out_get_mmap_position(const struct audio_stream_out *stream,
5955 struct audio_mmap_position *position)
5956{
5957 struct stream_out *out = (struct stream_out *)stream;
5958 ALOGVV("%s", __func__);
5959 if (position == NULL) {
5960 return -EINVAL;
5961 }
5962 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005963 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005964 return -ENOSYS;
5965 }
5966 if (out->pcm == NULL) {
5967 return -ENOSYS;
5968 }
5969
5970 struct timespec ts = { 0, 0 };
5971 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5972 if (ret < 0) {
5973 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5974 return ret;
5975 }
Phil Burkfe17efd2019-03-25 10:23:35 -07005976 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
5977 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07005978 return 0;
5979}
5980
5981
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005982/** audio_stream_in implementation **/
5983static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5984{
5985 struct stream_in *in = (struct stream_in *)stream;
5986
5987 return in->config.rate;
5988}
5989
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005990static int in_set_sample_rate(struct audio_stream *stream __unused,
5991 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005992{
5993 return -ENOSYS;
5994}
5995
5996static size_t in_get_buffer_size(const struct audio_stream *stream)
5997{
5998 struct stream_in *in = (struct stream_in *)stream;
5999
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006000 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6001 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006002 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
6003 return VOIP_IO_BUF_SIZE(in->config.rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE);
Mingming Yine62d7842013-10-25 16:26:03 -07006004 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6005 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306006 else if(audio_extn_cin_attached_usecase(in->usecase))
6007 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006008
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006009 return in->config.period_size * in->af_period_multiplier *
6010 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006011}
6012
6013static uint32_t in_get_channels(const struct audio_stream *stream)
6014{
6015 struct stream_in *in = (struct stream_in *)stream;
6016
6017 return in->channel_mask;
6018}
6019
6020static audio_format_t in_get_format(const struct audio_stream *stream)
6021{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006022 struct stream_in *in = (struct stream_in *)stream;
6023
6024 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006025}
6026
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006027static int in_set_format(struct audio_stream *stream __unused,
6028 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006029{
6030 return -ENOSYS;
6031}
6032
6033static int in_standby(struct audio_stream *stream)
6034{
6035 struct stream_in *in = (struct stream_in *)stream;
6036 struct audio_device *adev = in->dev;
6037 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306038 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6039 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006040 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306041
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006042 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006043 if (!in->standby && in->is_st_session) {
6044 ALOGD("%s: sound trigger pcm stop lab", __func__);
6045 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006046 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006047 in->standby = 1;
6048 }
6049
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006050 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006051 if (adev->adm_deregister_stream)
6052 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6053
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006054 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006055 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006056 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006057 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006058 voice_extn_compress_voip_close_input_stream(stream);
6059 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006060 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6061 do_stop = in->capture_started;
6062 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006063 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306064 if (audio_extn_cin_attached_usecase(in->usecase))
6065 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006066 }
6067
Arun Mirpuri5d170872019-03-26 13:21:31 -07006068 if (in->pcm) {
6069 ATRACE_BEGIN("pcm_in_close");
6070 pcm_close(in->pcm);
6071 ATRACE_END();
6072 in->pcm = NULL;
6073 }
6074
6075 if(do_stop) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006076 adev->enable_voicerx = false;
6077 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08006078 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006079 }
Quinn Malef6050362019-01-30 15:55:40 -08006080
6081 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6082 adev->num_va_sessions--;
6083
Eric Laurent150dbfe2013-02-27 14:31:02 -08006084 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006085 }
6086 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006087 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006088 return status;
6089}
6090
Aalique Grahame22e49102018-12-18 14:23:57 -08006091static int in_dump(const struct audio_stream *stream,
6092 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006093{
Aalique Grahame22e49102018-12-18 14:23:57 -08006094 struct stream_in *in = (struct stream_in *)stream;
6095
6096 // We try to get the lock for consistency,
6097 // but it isn't necessary for these variables.
6098 // If we're not in standby, we may be blocked on a read.
6099 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6100 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6101 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6102 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6103
6104 if (locked) {
6105 pthread_mutex_unlock(&in->lock);
6106 }
6107
6108 // dump error info
6109 (void)error_log_dump(
6110 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6111
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006112 return 0;
6113}
6114
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306115static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6116{
6117 if (!stream || !parms)
6118 return;
6119
6120 struct stream_in *in = (struct stream_in *)stream;
6121 struct audio_device *adev = in->dev;
6122
6123 card_status_t status;
6124 int card;
6125 if (parse_snd_card_status(parms, &card, &status) < 0)
6126 return;
6127
6128 pthread_mutex_lock(&adev->lock);
6129 bool valid_cb = (card == adev->snd_card);
6130 pthread_mutex_unlock(&adev->lock);
6131
6132 if (!valid_cb)
6133 return;
6134
6135 lock_input_stream(in);
6136 if (in->card_status != status)
6137 in->card_status = status;
6138 pthread_mutex_unlock(&in->lock);
6139
6140 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6141 use_case_table[in->usecase],
6142 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6143
6144 // a better solution would be to report error back to AF and let
6145 // it put the stream to standby
6146 if (status == CARD_STATUS_OFFLINE)
6147 in_standby(&in->stream.common);
6148
6149 return;
6150}
6151
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006152static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6153{
6154 struct stream_in *in = (struct stream_in *)stream;
6155 struct audio_device *adev = in->dev;
6156 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006157 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006158 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006159
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306160 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006161 parms = str_parms_create_str(kvpairs);
6162
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306163 if (!parms)
6164 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006165 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006166 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006167
6168 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6169 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006170 val = atoi(value);
6171 /* no audio source uses val == 0 */
6172 if ((in->source != val) && (val != 0)) {
6173 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006174 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6175 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6176 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006177 (in->config.rate == 8000 || in->config.rate == 16000 ||
6178 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006179 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006180 err = voice_extn_compress_voip_open_input_stream(in);
6181 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006182 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006183 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006184 }
6185 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006186 }
6187 }
6188
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006189 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6190 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006191 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006192 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6193
6194 // Workaround: If routing to an non existing usb device, fail gracefully
6195 // The routing request will otherwise block during 10 second
6196 int card;
6197 if (audio_is_usb_in_device(val) &&
6198 (card = get_alive_usb_card(parms)) >= 0) {
6199
6200 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6201 ret = -ENOSYS;
6202 } else {
6203
6204 in->device = val;
6205 /* If recording is in progress, change the tx device to new device */
6206 if (!in->standby && !in->is_st_session) {
6207 ALOGV("update input routing change");
6208 // inform adm before actual routing to prevent glitches.
6209 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006210 adev->adm_on_routing_change(adev->adm_data,
6211 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006212 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006213 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6214 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006215 }
6216 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006217 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006218 }
6219 }
6220
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306221 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6222 if (err >= 0) {
6223 strlcpy(in->profile, value, sizeof(in->profile));
6224 ALOGV("updating stream profile with value '%s'", in->profile);
6225 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6226 &adev->streams_input_cfg_list,
6227 in->device, in->flags, in->format,
6228 in->sample_rate, in->bit_width,
6229 in->profile, &in->app_type_cfg);
6230 }
6231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006232 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006233 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006234
6235 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306236error:
Eric Laurent994a6932013-07-17 11:51:42 -07006237 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006238 return ret;
6239}
6240
6241static char* in_get_parameters(const struct audio_stream *stream,
6242 const char *keys)
6243{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006244 struct stream_in *in = (struct stream_in *)stream;
6245 struct str_parms *query = str_parms_create_str(keys);
6246 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006247 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006248
6249 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006250 if (reply) {
6251 str_parms_destroy(reply);
6252 }
6253 if (query) {
6254 str_parms_destroy(query);
6255 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006256 ALOGE("in_get_parameters: failed to create query or reply");
6257 return NULL;
6258 }
6259
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006260 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006261
6262 voice_extn_in_get_parameters(in, query, reply);
6263
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006264 stream_get_parameter_channels(query, reply,
6265 &in->supported_channel_masks[0]);
6266 stream_get_parameter_formats(query, reply,
6267 &in->supported_formats[0]);
6268 stream_get_parameter_rates(query, reply,
6269 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006270 str = str_parms_to_str(reply);
6271 str_parms_destroy(query);
6272 str_parms_destroy(reply);
6273
6274 ALOGV("%s: exit: returns - %s", __func__, str);
6275 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006276}
6277
Aalique Grahame22e49102018-12-18 14:23:57 -08006278static int in_set_gain(struct audio_stream_in *stream,
6279 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006280{
Aalique Grahame22e49102018-12-18 14:23:57 -08006281 struct stream_in *in = (struct stream_in *)stream;
6282 char mixer_ctl_name[128];
6283 struct mixer_ctl *ctl;
6284 int ctl_value;
6285
6286 ALOGV("%s: gain %f", __func__, gain);
6287
6288 if (stream == NULL)
6289 return -EINVAL;
6290
6291 /* in_set_gain() only used to silence MMAP capture for now */
6292 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6293 return -ENOSYS;
6294
6295 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6296
6297 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6298 if (!ctl) {
6299 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6300 __func__, mixer_ctl_name);
6301 return -ENOSYS;
6302 }
6303
6304 if (gain < RECORD_GAIN_MIN)
6305 gain = RECORD_GAIN_MIN;
6306 else if (gain > RECORD_GAIN_MAX)
6307 gain = RECORD_GAIN_MAX;
6308 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6309
6310 mixer_ctl_set_value(ctl, 0, ctl_value);
6311
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006312 return 0;
6313}
6314
6315static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6316 size_t bytes)
6317{
6318 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306319
6320 if (in == NULL) {
6321 ALOGE("%s: stream_in ptr is NULL", __func__);
6322 return -EINVAL;
6323 }
6324
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006325 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306326 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306327 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006328
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006329 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306330
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006331 if (in->is_st_session) {
6332 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6333 /* Read from sound trigger HAL */
6334 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006335 if (in->standby) {
6336 adev->num_va_sessions++;
6337 in->standby = 0;
6338 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006339 pthread_mutex_unlock(&in->lock);
6340 return bytes;
6341 }
6342
Haynes Mathew George16081042017-05-31 17:16:49 -07006343 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6344 ret = -ENOSYS;
6345 goto exit;
6346 }
6347
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006348 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6349 !in->standby && adev->adm_routing_changed) {
6350 ret = -ENOSYS;
6351 goto exit;
6352 }
6353
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006354 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006355 pthread_mutex_lock(&adev->lock);
6356 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6357 ret = voice_extn_compress_voip_start_input_stream(in);
6358 else
6359 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006360 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6361 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006362 pthread_mutex_unlock(&adev->lock);
6363 if (ret != 0) {
6364 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006365 }
6366 in->standby = 0;
6367 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006368
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006369 // what's the duration requested by the client?
6370 long ns = 0;
6371
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306372 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006373 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6374 in->config.rate;
6375
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006376 ret = request_in_focus(in, ns);
6377 if (ret != 0)
6378 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006379 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006380
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306381 if (audio_extn_cin_attached_usecase(in->usecase)) {
6382 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6383 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306384 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006385 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306386 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006387 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006388 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006389 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006390 } else if (audio_extn_ffv_get_stream() == in) {
6391 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306392 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006393 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306394 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6395 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6396 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6397 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306398 ret = -EINVAL;
6399 goto exit;
6400 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306401 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306402 ret = -errno;
6403 }
6404 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306405 /* bytes read is always set to bytes for non compress usecases */
6406 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006407 }
6408
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006409 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006411 /*
Quinn Malef6050362019-01-30 15:55:40 -08006412 * Instead of writing zeroes here, we could trust the hardware to always
6413 * provide zeroes when muted. This is also muted with voice recognition
6414 * usecases so that other clients do not have access to voice recognition
6415 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006416 */
Quinn Malef6050362019-01-30 15:55:40 -08006417 if ((ret == 0 && voice_get_mic_mute(adev) &&
6418 !voice_is_in_call_rec_stream(in) &&
6419 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6420 (adev->num_va_sessions &&
6421 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6422 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6423 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006424 memset(buffer, 0, bytes);
6425
6426exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306427 frame_size = audio_stream_in_frame_size(stream);
6428 if (frame_size > 0)
6429 in->frames_read += bytes_read/frame_size;
6430
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006431 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306432 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006433 pthread_mutex_unlock(&in->lock);
6434
6435 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306436 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306437 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306438 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306439 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306440 in->standby = true;
6441 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306442 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6443 bytes_read = bytes;
6444 memset(buffer, 0, bytes);
6445 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006446 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006447 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6448 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006449 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306450 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306451 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006452 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306453 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006454}
6455
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006456static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006457{
6458 return 0;
6459}
6460
Aalique Grahame22e49102018-12-18 14:23:57 -08006461static int in_get_capture_position(const struct audio_stream_in *stream,
6462 int64_t *frames, int64_t *time)
6463{
6464 if (stream == NULL || frames == NULL || time == NULL) {
6465 return -EINVAL;
6466 }
6467 struct stream_in *in = (struct stream_in *)stream;
6468 int ret = -ENOSYS;
6469
6470 lock_input_stream(in);
6471 // note: ST sessions do not close the alsa pcm driver synchronously
6472 // on standby. Therefore, we may return an error even though the
6473 // pcm stream is still opened.
6474 if (in->standby) {
6475 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6476 "%s stream in standby but pcm not NULL for non ST session", __func__);
6477 goto exit;
6478 }
6479 if (in->pcm) {
6480 struct timespec timestamp;
6481 unsigned int avail;
6482 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6483 *frames = in->frames_read + avail;
6484 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6485 ret = 0;
6486 }
6487 }
6488exit:
6489 pthread_mutex_unlock(&in->lock);
6490 return ret;
6491}
6492
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006493static int add_remove_audio_effect(const struct audio_stream *stream,
6494 effect_handle_t effect,
6495 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006496{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006497 struct stream_in *in = (struct stream_in *)stream;
6498 int status = 0;
6499 effect_descriptor_t desc;
6500
6501 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006502 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6503
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006504 if (status != 0)
6505 return status;
6506
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006507 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006508 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006509 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006510 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006511 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006512 in->enable_aec != enable &&
6513 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6514 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006515 if (!enable)
6516 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6517 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6518 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6519 in->dev->enable_voicerx = enable;
6520 struct audio_usecase *usecase;
6521 struct listnode *node;
6522 list_for_each(node, &in->dev->usecase_list) {
6523 usecase = node_to_item(node, struct audio_usecase, list);
6524 if (usecase->type == PCM_PLAYBACK)
6525 select_devices(in->dev, usecase->id);
6526 }
6527 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006528 if (!in->standby) {
6529 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6530 select_devices(in->dev, in->usecase);
6531 }
6532
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006533 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006534 if (in->enable_ns != enable &&
6535 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6536 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006537 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006538 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6539 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006540 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6541 select_devices(in->dev, in->usecase);
6542 } else
6543 select_devices(in->dev, in->usecase);
6544 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006545 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006546 pthread_mutex_unlock(&in->dev->lock);
6547 pthread_mutex_unlock(&in->lock);
6548
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006549 return 0;
6550}
6551
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006552static int in_add_audio_effect(const struct audio_stream *stream,
6553 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006554{
Eric Laurent994a6932013-07-17 11:51:42 -07006555 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006556 return add_remove_audio_effect(stream, effect, true);
6557}
6558
6559static int in_remove_audio_effect(const struct audio_stream *stream,
6560 effect_handle_t effect)
6561{
Eric Laurent994a6932013-07-17 11:51:42 -07006562 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006563 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006564}
6565
Derek Chenf939fb72018-11-13 13:34:41 -08006566streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6567 audio_io_handle_t input)
6568{
6569 struct listnode *node;
6570
6571 list_for_each(node, &dev->active_inputs_list) {
6572 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6573 streams_input_ctxt_t,
6574 list);
6575 if (in_ctxt->input->capture_handle == input) {
6576 return in_ctxt;
6577 }
6578 }
6579 return NULL;
6580}
6581
6582streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6583 audio_io_handle_t output)
6584{
6585 struct listnode *node;
6586
6587 list_for_each(node, &dev->active_outputs_list) {
6588 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6589 streams_output_ctxt_t,
6590 list);
6591 if (out_ctxt->output->handle == output) {
6592 return out_ctxt;
6593 }
6594 }
6595 return NULL;
6596}
6597
Haynes Mathew George16081042017-05-31 17:16:49 -07006598static int in_stop(const struct audio_stream_in* stream)
6599{
6600 struct stream_in *in = (struct stream_in *)stream;
6601 struct audio_device *adev = in->dev;
6602
6603 int ret = -ENOSYS;
6604 ALOGV("%s", __func__);
6605 pthread_mutex_lock(&adev->lock);
6606 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6607 in->capture_started && in->pcm != NULL) {
6608 pcm_stop(in->pcm);
6609 ret = stop_input_stream(in);
6610 in->capture_started = false;
6611 }
6612 pthread_mutex_unlock(&adev->lock);
6613 return ret;
6614}
6615
6616static int in_start(const struct audio_stream_in* stream)
6617{
6618 struct stream_in *in = (struct stream_in *)stream;
6619 struct audio_device *adev = in->dev;
6620 int ret = -ENOSYS;
6621
6622 ALOGV("%s in %p", __func__, in);
6623 pthread_mutex_lock(&adev->lock);
6624 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6625 !in->capture_started && in->pcm != NULL) {
6626 if (!in->capture_started) {
6627 ret = start_input_stream(in);
6628 if (ret == 0) {
6629 in->capture_started = true;
6630 }
6631 }
6632 }
6633 pthread_mutex_unlock(&adev->lock);
6634 return ret;
6635}
6636
Phil Burke0a86d12019-02-16 22:28:11 -08006637// Read offset for the positional timestamp from a persistent vendor property.
6638// This is to workaround apparent inaccuracies in the timing information that
6639// is used by the AAudio timing model. The inaccuracies can cause glitches.
6640static int64_t in_get_mmap_time_offset() {
6641 const int32_t kDefaultOffsetMicros = 0;
6642 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006643 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006644 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6645 return mmap_time_offset_micros * (int64_t)1000;
6646}
6647
Haynes Mathew George16081042017-05-31 17:16:49 -07006648static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6649 int32_t min_size_frames,
6650 struct audio_mmap_buffer_info *info)
6651{
6652 struct stream_in *in = (struct stream_in *)stream;
6653 struct audio_device *adev = in->dev;
6654 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006655 unsigned int offset1 = 0;
6656 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006657 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006658 uint32_t mmap_size = 0;
6659 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006660
6661 pthread_mutex_lock(&adev->lock);
6662 ALOGV("%s in %p", __func__, in);
6663
Sharad Sanglec6f32552018-05-04 16:15:38 +05306664 if (CARD_STATUS_OFFLINE == in->card_status||
6665 CARD_STATUS_OFFLINE == adev->card_status) {
6666 ALOGW("in->card_status or adev->card_status offline, try again");
6667 ret = -EIO;
6668 goto exit;
6669 }
6670
Haynes Mathew George16081042017-05-31 17:16:49 -07006671 if (info == NULL || min_size_frames == 0) {
6672 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6673 ret = -EINVAL;
6674 goto exit;
6675 }
6676 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6677 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6678 ALOGV("%s in %p", __func__, in);
6679 ret = -ENOSYS;
6680 goto exit;
6681 }
6682 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6683 if (in->pcm_device_id < 0) {
6684 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6685 __func__, in->pcm_device_id, in->usecase);
6686 ret = -EINVAL;
6687 goto exit;
6688 }
6689
6690 adjust_mmap_period_count(&in->config, min_size_frames);
6691
6692 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6693 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6694 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6695 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306696 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306697 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6698 in->card_status = CARD_STATUS_OFFLINE;
6699 adev->card_status = CARD_STATUS_OFFLINE;
6700 ret = -EIO;
6701 goto exit;
6702 }
6703
Haynes Mathew George16081042017-05-31 17:16:49 -07006704 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6705 step = "open";
6706 ret = -ENODEV;
6707 goto exit;
6708 }
6709
6710 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6711 if (ret < 0) {
6712 step = "begin";
6713 goto exit;
6714 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006715
Arun Mirpuri5d170872019-03-26 13:21:31 -07006716 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6717 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6718 info->burst_size_frames = in->config.period_size;
6719 ret = platform_get_mmap_data_fd(adev->platform,
6720 in->pcm_device_id, 1 /*capture*/,
6721 &info->shared_memory_fd,
6722 &mmap_size);
6723 if (ret < 0) {
6724 // Fall back to non exclusive mode
6725 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6726 } else {
6727 if (mmap_size < buffer_size) {
6728 step = "mmap";
6729 goto exit;
6730 }
6731 // FIXME: indicate exclusive mode support by returning a negative buffer size
6732 info->buffer_size_frames *= -1;
6733 }
6734
6735 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006736
6737 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6738 if (ret < 0) {
6739 step = "commit";
6740 goto exit;
6741 }
6742
Phil Burke0a86d12019-02-16 22:28:11 -08006743 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
6744
Haynes Mathew George16081042017-05-31 17:16:49 -07006745 in->standby = false;
6746 ret = 0;
6747
6748 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6749 __func__, info->shared_memory_address, info->buffer_size_frames);
6750
6751exit:
6752 if (ret != 0) {
6753 if (in->pcm == NULL) {
6754 ALOGE("%s: %s - %d", __func__, step, ret);
6755 } else {
6756 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6757 pcm_close(in->pcm);
6758 in->pcm = NULL;
6759 }
6760 }
6761 pthread_mutex_unlock(&adev->lock);
6762 return ret;
6763}
6764
6765static int in_get_mmap_position(const struct audio_stream_in *stream,
6766 struct audio_mmap_position *position)
6767{
6768 struct stream_in *in = (struct stream_in *)stream;
6769 ALOGVV("%s", __func__);
6770 if (position == NULL) {
6771 return -EINVAL;
6772 }
6773 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6774 return -ENOSYS;
6775 }
6776 if (in->pcm == NULL) {
6777 return -ENOSYS;
6778 }
6779 struct timespec ts = { 0, 0 };
6780 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6781 if (ret < 0) {
6782 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6783 return ret;
6784 }
Phil Burke0a86d12019-02-16 22:28:11 -08006785 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6786 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006787 return 0;
6788}
6789
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306790static int in_get_active_microphones(const struct audio_stream_in *stream,
6791 struct audio_microphone_characteristic_t *mic_array,
6792 size_t *mic_count) {
6793 struct stream_in *in = (struct stream_in *)stream;
6794 struct audio_device *adev = in->dev;
6795 ALOGVV("%s", __func__);
6796
6797 lock_input_stream(in);
6798 pthread_mutex_lock(&adev->lock);
6799 int ret = platform_get_active_microphones(adev->platform,
6800 audio_channel_count_from_in_mask(in->channel_mask),
6801 in->usecase, mic_array, mic_count);
6802 pthread_mutex_unlock(&adev->lock);
6803 pthread_mutex_unlock(&in->lock);
6804
6805 return ret;
6806}
6807
6808static int adev_get_microphones(const struct audio_hw_device *dev,
6809 struct audio_microphone_characteristic_t *mic_array,
6810 size_t *mic_count) {
6811 struct audio_device *adev = (struct audio_device *)dev;
6812 ALOGVV("%s", __func__);
6813
6814 pthread_mutex_lock(&adev->lock);
6815 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6816 pthread_mutex_unlock(&adev->lock);
6817
6818 return ret;
6819}
juyuchendb308c22019-01-21 11:57:17 -07006820
6821static void in_update_sink_metadata(struct audio_stream_in *stream,
6822 const struct sink_metadata *sink_metadata) {
6823
6824 if (stream == NULL
6825 || sink_metadata == NULL
6826 || sink_metadata->tracks == NULL) {
6827 return;
6828 }
6829
6830 int error = 0;
6831 struct stream_in *in = (struct stream_in *)stream;
6832 struct audio_device *adev = in->dev;
6833 audio_devices_t device = AUDIO_DEVICE_NONE;
6834
6835 if (sink_metadata->track_count != 0)
6836 device = sink_metadata->tracks->dest_device;
6837
6838 lock_input_stream(in);
6839 pthread_mutex_lock(&adev->lock);
6840 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
6841
6842 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
6843 && device != AUDIO_DEVICE_NONE
6844 && adev->voice_tx_output != NULL) {
6845 /* Use the rx device from afe-proxy record to route voice call because
6846 there is no routing if tx device is on primary hal and rx device
6847 is on other hal during voice call. */
6848 adev->voice_tx_output->devices = device;
6849
6850 if (!voice_is_call_state_active(adev)) {
6851 if (adev->mode == AUDIO_MODE_IN_CALL) {
6852 adev->current_call_output = adev->voice_tx_output;
6853 error = voice_start_call(adev);
6854 if (error != 0)
6855 ALOGE("%s: start voice call failed %d", __func__, error);
6856 }
6857 } else {
6858 adev->current_call_output = adev->voice_tx_output;
6859 voice_update_devices_for_all_voice_usecases(adev);
6860 }
6861 }
6862
6863 pthread_mutex_unlock(&adev->lock);
6864 pthread_mutex_unlock(&in->lock);
6865}
6866
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306867int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006868 audio_io_handle_t handle,
6869 audio_devices_t devices,
6870 audio_output_flags_t flags,
6871 struct audio_config *config,
6872 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04006873 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006874{
6875 struct audio_device *adev = (struct audio_device *)dev;
6876 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05306877 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006878 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006879 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306880 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006881 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6882 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6883 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6884 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006885 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07006886 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
6887 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006888 bool force_haptic_path =
6889 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07006890 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006891
kunleizdff872d2018-08-20 14:40:33 +08006892 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006893 is_usb_dev = false;
6894 devices = AUDIO_DEVICE_OUT_SPEAKER;
6895 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6896 __func__, devices);
6897 }
6898
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006899 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306900
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006901 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6902
Mingming Yin3a941d42016-02-17 18:08:05 -08006903 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04006904 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
6905 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306906
6907
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006908 if (!out) {
6909 return -ENOMEM;
6910 }
6911
Haynes Mathew George204045b2015-02-25 20:32:03 -08006912 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006913 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306914 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006915 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006916 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006918 if (devices == AUDIO_DEVICE_NONE)
6919 devices = AUDIO_DEVICE_OUT_SPEAKER;
6920
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006921 out->flags = flags;
6922 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006923 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006924 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006925 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306926 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306927 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6928 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6929 else
6930 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006931 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006932 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006933 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306934 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306935 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306936 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006937 out->hal_output_suspend_supported = 0;
6938 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306939 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306940 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306941 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006942
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306943 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306944 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006945 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6946
Aalique Grahame22e49102018-12-18 14:23:57 -08006947 if (direct_dev &&
6948 (audio_is_linear_pcm(out->format) ||
6949 config->format == AUDIO_FORMAT_DEFAULT) &&
6950 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6951 audio_format_t req_format = config->format;
6952 audio_channel_mask_t req_channel_mask = config->channel_mask;
6953 uint32_t req_sample_rate = config->sample_rate;
6954
6955 pthread_mutex_lock(&adev->lock);
6956 if (is_hdmi) {
6957 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6958 ret = read_hdmi_sink_caps(out);
6959 if (config->sample_rate == 0)
6960 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6961 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6962 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6963 if (config->format == AUDIO_FORMAT_DEFAULT)
6964 config->format = AUDIO_FORMAT_PCM_16_BIT;
6965 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006966 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6967 &config->format,
6968 &out->supported_formats[0],
6969 MAX_SUPPORTED_FORMATS,
6970 &config->channel_mask,
6971 &out->supported_channel_masks[0],
6972 MAX_SUPPORTED_CHANNEL_MASKS,
6973 &config->sample_rate,
6974 &out->supported_sample_rates[0],
6975 MAX_SUPPORTED_SAMPLE_RATES);
6976 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006977 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006978
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006979 pthread_mutex_unlock(&adev->lock);
6980 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006981 if (ret == -ENOSYS) {
6982 /* ignore and go with default */
6983 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006984 }
6985 // For MMAP NO IRQ, allow conversions in ADSP
6986 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6987 goto error_open;
6988 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006989 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006990 goto error_open;
6991 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006992
6993 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6994 config->sample_rate = req_sample_rate;
6995 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6996 config->channel_mask = req_channel_mask;
6997 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6998 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006999 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007000
7001 out->sample_rate = config->sample_rate;
7002 out->channel_mask = config->channel_mask;
7003 out->format = config->format;
7004 if (is_hdmi) {
7005 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7006 out->config = pcm_config_hdmi_multi;
7007 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7008 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7009 out->config = pcm_config_mmap_playback;
7010 out->stream.start = out_start;
7011 out->stream.stop = out_stop;
7012 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7013 out->stream.get_mmap_position = out_get_mmap_position;
7014 } else {
7015 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7016 out->config = pcm_config_hifi;
7017 }
7018
7019 out->config.rate = out->sample_rate;
7020 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7021 if (is_hdmi) {
7022 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7023 audio_bytes_per_sample(out->format));
7024 }
7025 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007026 }
7027
Derek Chenf6318be2017-06-12 17:16:24 -04007028 /* validate bus device address */
7029 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7030 /* extract car audio stream index */
7031 out->car_audio_stream =
7032 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7033 if (out->car_audio_stream < 0) {
7034 ALOGE("%s: invalid car audio stream %x",
7035 __func__, out->car_audio_stream);
7036 ret = -EINVAL;
7037 goto error_open;
7038 }
7039 /* save car audio stream and address for bus device */
7040 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
7041 ALOGV("%s: address %s, car_audio_stream %x",
7042 __func__, out->address, out->car_audio_stream);
7043 }
7044
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007045 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007046 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007047 if (!voice_extn_is_compress_voip_supported()) {
7048 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7049 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007050 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7051 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007052 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7053 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007054 out->volume_l = INVALID_OUT_VOLUME;
7055 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007056
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007057 out->config = default_pcm_config_voip_copp;
7058 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7059 out->config.rate = out->sample_rate;
7060 }
7061 } else {
7062 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7063 voice_extn_compress_voip_is_active(out->dev)) &&
7064 (voice_extn_compress_voip_is_config_supported(config))) {
7065 ret = voice_extn_compress_voip_open_output_stream(out);
7066 if (ret != 0) {
7067 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7068 __func__, ret);
7069 goto error_open;
7070 }
7071 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007072 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007073 } else if (audio_is_linear_pcm(out->format) &&
7074 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7075 out->channel_mask = config->channel_mask;
7076 out->sample_rate = config->sample_rate;
7077 out->format = config->format;
7078 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7079 // does this change?
7080 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7081 out->config.rate = config->sample_rate;
7082 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7083 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7084 audio_bytes_per_sample(config->format));
7085 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007086 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307087 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307088 pthread_mutex_lock(&adev->lock);
7089 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7090 pthread_mutex_unlock(&adev->lock);
7091
7092 // reject offload during card offline to allow
7093 // fallback to s/w paths
7094 if (offline) {
7095 ret = -ENODEV;
7096 goto error_open;
7097 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007098
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007099 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7100 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7101 ALOGE("%s: Unsupported Offload information", __func__);
7102 ret = -EINVAL;
7103 goto error_open;
7104 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007105
Atul Khare3fa6e542017-08-09 00:56:17 +05307106 if (config->offload_info.format == 0)
7107 config->offload_info.format = config->format;
7108 if (config->offload_info.sample_rate == 0)
7109 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007110
Mingming Yin90310102013-11-13 16:57:00 -08007111 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307112 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007113 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007114 ret = -EINVAL;
7115 goto error_open;
7116 }
7117
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007118 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7119 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7120 (audio_extn_passthru_is_passthrough_stream(out)) &&
7121 !((config->sample_rate == 48000) ||
7122 (config->sample_rate == 96000) ||
7123 (config->sample_rate == 192000))) {
7124 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7125 __func__, config->sample_rate, config->offload_info.format);
7126 ret = -EINVAL;
7127 goto error_open;
7128 }
7129
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007130 out->compr_config.codec = (struct snd_codec *)
7131 calloc(1, sizeof(struct snd_codec));
7132
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007133 if (!out->compr_config.codec) {
7134 ret = -ENOMEM;
7135 goto error_open;
7136 }
7137
Dhananjay Kumarac341582017-02-23 23:42:25 +05307138 out->stream.pause = out_pause;
7139 out->stream.resume = out_resume;
7140 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307141 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307142 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007143 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307144 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007145 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307146 } else {
7147 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7148 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007149 }
vivek mehta446c3962015-09-14 10:57:35 -07007150
7151 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007152 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7153 config->format == 0 && config->sample_rate == 0 &&
7154 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007155 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007156 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7157 } else {
7158 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7159 ret = -EEXIST;
7160 goto error_open;
7161 }
vivek mehta446c3962015-09-14 10:57:35 -07007162 }
7163
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007164 if (config->offload_info.channel_mask)
7165 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007166 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007167 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007168 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007169 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307170 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007171 ret = -EINVAL;
7172 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007173 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007174
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007175 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007176 out->sample_rate = config->offload_info.sample_rate;
7177
Mingming Yin3ee55c62014-08-04 14:23:35 -07007178 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007179
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307180 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307181 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307182 audio_extn_dolby_send_ddp_endp_params(adev);
7183 audio_extn_dolby_set_dmid(adev);
7184 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007185
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007186 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007187 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007188 out->compr_config.codec->bit_rate =
7189 config->offload_info.bit_rate;
7190 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307191 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007192 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307193 /* Update bit width only for non passthrough usecases.
7194 * For passthrough usecases, the output will always be opened @16 bit
7195 */
7196 if (!audio_extn_passthru_is_passthrough_stream(out))
7197 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307198
7199 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7200 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7201 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7202
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007203 /*TODO: Do we need to change it for passthrough */
7204 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007205
Manish Dewangana6fc5442015-08-24 20:30:31 +05307206 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7207 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307208 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307209 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307210 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7211 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307212
7213 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7214 AUDIO_FORMAT_PCM) {
7215
7216 /*Based on platform support, configure appropriate alsa format for corresponding
7217 *hal input format.
7218 */
7219 out->compr_config.codec->format = hal_format_to_alsa(
7220 config->offload_info.format);
7221
Ashish Jain83a6cc22016-06-28 14:34:17 +05307222 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307223 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307224 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307225
Dhananjay Kumarac341582017-02-23 23:42:25 +05307226 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307227 *hal input format and alsa format might differ based on platform support.
7228 */
7229 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307230 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307231
7232 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7233
7234 /* Check if alsa session is configured with the same format as HAL input format,
7235 * if not then derive correct fragment size needed to accomodate the
7236 * conversion of HAL input format to alsa format.
7237 */
7238 audio_extn_utils_update_direct_pcm_fragment_size(out);
7239
7240 /*if hal input and output fragment size is different this indicates HAL input format is
7241 *not same as the alsa format
7242 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307243 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307244 /*Allocate a buffer to convert input data to the alsa configured format.
7245 *size of convert buffer is equal to the size required to hold one fragment size
7246 *worth of pcm data, this is because flinger does not write more than fragment_size
7247 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307248 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7249 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307250 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7251 ret = -ENOMEM;
7252 goto error_open;
7253 }
7254 }
7255 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7256 out->compr_config.fragment_size =
7257 audio_extn_passthru_get_buffer_size(&config->offload_info);
7258 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7259 } else {
7260 out->compr_config.fragment_size =
7261 platform_get_compress_offload_buffer_size(&config->offload_info);
7262 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7263 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007264
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307265 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7266 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7267 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007268 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307269 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007270
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307271 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7272 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7273 }
7274
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007275 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7276 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007277
Manish Dewangan69426c82017-01-30 17:35:36 +05307278 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7279 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7280 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7281 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7282 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7283 } else {
7284 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7285 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007286
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307287 memset(&out->channel_map_param, 0,
7288 sizeof(struct audio_out_channel_map_param));
7289
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007290 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307291 out->send_next_track_params = false;
7292 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007293 out->offload_state = OFFLOAD_STATE_IDLE;
7294 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007295 out->writeAt.tv_sec = 0;
7296 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007297
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007298 audio_extn_dts_create_state_notifier_node(out->usecase);
7299
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007300 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7301 __func__, config->offload_info.version,
7302 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307303
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307304 /* Check if DSD audio format is supported in codec
7305 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307306 */
7307
7308 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307309 (!platform_check_codec_dsd_support(adev->platform) ||
7310 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307311 ret = -EINVAL;
7312 goto error_open;
7313 }
7314
Ashish Jain5106d362016-05-11 19:23:33 +05307315 /* Disable gapless if any of the following is true
7316 * passthrough playback
7317 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307318 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307319 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307320 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307321 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007322 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307323 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307324 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307325 check_and_set_gapless_mode(adev, false);
7326 } else
7327 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007328
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307329 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007330 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7331 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307332 if (config->format == AUDIO_FORMAT_DSD) {
7333 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7334 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7335 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007336
7337 create_offload_callback_thread(out);
7338
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007339 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007340 switch (config->sample_rate) {
7341 case 0:
7342 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7343 break;
7344 case 8000:
7345 case 16000:
7346 case 48000:
7347 out->sample_rate = config->sample_rate;
7348 break;
7349 default:
7350 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7351 config->sample_rate);
7352 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7353 ret = -EINVAL;
7354 goto error_open;
7355 }
7356 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7357 switch (config->channel_mask) {
7358 case AUDIO_CHANNEL_NONE:
7359 case AUDIO_CHANNEL_OUT_STEREO:
7360 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7361 break;
7362 default:
7363 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7364 config->channel_mask);
7365 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7366 ret = -EINVAL;
7367 goto error_open;
7368 }
7369 switch (config->format) {
7370 case AUDIO_FORMAT_DEFAULT:
7371 case AUDIO_FORMAT_PCM_16_BIT:
7372 out->format = AUDIO_FORMAT_PCM_16_BIT;
7373 break;
7374 default:
7375 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7376 config->format);
7377 config->format = AUDIO_FORMAT_PCM_16_BIT;
7378 ret = -EINVAL;
7379 goto error_open;
7380 }
7381
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307382 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007383 if (ret != 0) {
7384 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007385 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007386 goto error_open;
7387 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007388 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007389 switch (config->sample_rate) {
7390 case 0:
7391 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7392 break;
7393 case 8000:
7394 case 16000:
7395 case 48000:
7396 out->sample_rate = config->sample_rate;
7397 break;
7398 default:
7399 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7400 config->sample_rate);
7401 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7402 ret = -EINVAL;
7403 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007404 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007405 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7406 switch (config->channel_mask) {
7407 case AUDIO_CHANNEL_NONE:
7408 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7409 break;
7410 case AUDIO_CHANNEL_OUT_STEREO:
7411 out->channel_mask = config->channel_mask;
7412 break;
7413 default:
7414 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7415 config->channel_mask);
7416 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7417 ret = -EINVAL;
7418 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007419 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007420 switch (config->format) {
7421 case AUDIO_FORMAT_DEFAULT:
7422 out->format = AUDIO_FORMAT_PCM_16_BIT;
7423 break;
7424 case AUDIO_FORMAT_PCM_16_BIT:
7425 out->format = config->format;
7426 break;
7427 default:
7428 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7429 config->format);
7430 config->format = AUDIO_FORMAT_PCM_16_BIT;
7431 ret = -EINVAL;
7432 break;
7433 }
7434 if (ret != 0)
7435 goto error_open;
7436
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007437 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7438 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007439 out->config.rate = out->sample_rate;
7440 out->config.channels =
7441 audio_channel_count_from_out_mask(out->channel_mask);
7442 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007443 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007444 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307445 unsigned int channels = 0;
7446 /*Update config params to default if not set by the caller*/
7447 if (config->sample_rate == 0)
7448 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7449 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7450 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7451 if (config->format == AUDIO_FORMAT_DEFAULT)
7452 config->format = AUDIO_FORMAT_PCM_16_BIT;
7453
7454 channels = audio_channel_count_from_out_mask(out->channel_mask);
7455
Varun Balaraje49253e2017-07-06 19:48:56 +05307456 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7457 out->usecase = get_interactive_usecase(adev);
7458 out->config = pcm_config_low_latency;
7459 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307460 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007461 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7462 out->flags);
7463 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007464 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7465 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7466 out->config = pcm_config_mmap_playback;
7467 out->stream.start = out_start;
7468 out->stream.stop = out_stop;
7469 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7470 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307471 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7472 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007473 out->hal_output_suspend_supported =
7474 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7475 out->dynamic_pm_qos_config_supported =
7476 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7477 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007478 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7479 } else {
7480 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7481 //the mixer path will be a string similar to "low-latency-playback resume"
7482 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7483 strlcat(out->pm_qos_mixer_path,
7484 " resume", MAX_MIXER_PATH_LEN);
7485 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7486 out->pm_qos_mixer_path);
7487 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307488 out->config = pcm_config_low_latency;
7489 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7490 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7491 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307492 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7493 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7494 if (out->config.period_size <= 0) {
7495 ALOGE("Invalid configuration period size is not valid");
7496 ret = -EINVAL;
7497 goto error_open;
7498 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007499 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7500 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7501 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007502 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7503 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7504 out->config = pcm_config_haptics_audio;
7505 if (force_haptic_path)
7506 adev->haptics_config = pcm_config_haptics_audio;
7507 else
7508 adev->haptics_config = pcm_config_haptics;
7509
7510 out->config.channels =
7511 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7512
7513 if (force_haptic_path) {
7514 out->config.channels = 1;
7515 adev->haptics_config.channels = 1;
7516 } else
7517 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Derek Chenf6318be2017-06-12 17:16:24 -04007518 } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7519 ret = audio_extn_auto_hal_open_output_stream(out);
7520 if (ret) {
7521 ALOGE("%s: Failed to open output stream for bus device", __func__);
7522 ret = -EINVAL;
7523 goto error_open;
7524 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307525 } else {
7526 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007527 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7528 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307529 }
7530 out->hal_ip_format = format = out->format;
7531 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7532 out->hal_op_format = pcm_format_to_hal(out->config.format);
7533 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7534 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007535 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307536 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307537 if (out->hal_ip_format != out->hal_op_format) {
7538 uint32_t buffer_size = out->config.period_size *
7539 format_to_bitwidth_table[out->hal_op_format] *
7540 out->config.channels;
7541 out->convert_buffer = calloc(1, buffer_size);
7542 if (out->convert_buffer == NULL){
7543 ALOGE("Allocation failed for convert buffer for size %d",
7544 out->compr_config.fragment_size);
7545 ret = -ENOMEM;
7546 goto error_open;
7547 }
7548 ALOGD("Convert buffer allocated of size %d", buffer_size);
7549 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007550 }
7551
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007552 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7553 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307554
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007555 /* TODO remove this hardcoding and check why width is zero*/
7556 if (out->bit_width == 0)
7557 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307558 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007559 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007560 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307561 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307562 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007563 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007564 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7565 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007566 if(adev->primary_output == NULL)
7567 adev->primary_output = out;
7568 else {
7569 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007570 ret = -EEXIST;
7571 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007572 }
7573 }
7574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007575 /* Check if this usecase is already existing */
7576 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007577 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7578 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007579 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007580 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007581 ret = -EEXIST;
7582 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007583 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007584
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007585 pthread_mutex_unlock(&adev->lock);
7586
7587 out->stream.common.get_sample_rate = out_get_sample_rate;
7588 out->stream.common.set_sample_rate = out_set_sample_rate;
7589 out->stream.common.get_buffer_size = out_get_buffer_size;
7590 out->stream.common.get_channels = out_get_channels;
7591 out->stream.common.get_format = out_get_format;
7592 out->stream.common.set_format = out_set_format;
7593 out->stream.common.standby = out_standby;
7594 out->stream.common.dump = out_dump;
7595 out->stream.common.set_parameters = out_set_parameters;
7596 out->stream.common.get_parameters = out_get_parameters;
7597 out->stream.common.add_audio_effect = out_add_audio_effect;
7598 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7599 out->stream.get_latency = out_get_latency;
7600 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007601#ifdef NO_AUDIO_OUT
7602 out->stream.write = out_write_for_no_output;
7603#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007604 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007605#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007606 out->stream.get_render_position = out_get_render_position;
7607 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007608 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007609
Haynes Mathew George16081042017-05-31 17:16:49 -07007610 if (out->realtime)
7611 out->af_period_multiplier = af_period_multiplier;
7612 else
7613 out->af_period_multiplier = 1;
7614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007615 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007616 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007617 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007618
7619 config->format = out->stream.common.get_format(&out->stream.common);
7620 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7621 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307622 register_format(out->format, out->supported_formats);
7623 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7624 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007625
Aalique Grahame22e49102018-12-18 14:23:57 -08007626 out->error_log = error_log_create(
7627 ERROR_LOG_ENTRIES,
7628 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7629
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307630 /*
7631 By locking output stream before registering, we allow the callback
7632 to update stream's state only after stream's initial state is set to
7633 adev state.
7634 */
7635 lock_output_stream(out);
7636 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7637 pthread_mutex_lock(&adev->lock);
7638 out->card_status = adev->card_status;
7639 pthread_mutex_unlock(&adev->lock);
7640 pthread_mutex_unlock(&out->lock);
7641
Aalique Grahame22e49102018-12-18 14:23:57 -08007642 stream_app_type_cfg_init(&out->app_type_cfg);
7643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007644 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307645 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007646 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007647
7648 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7649 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7650 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007651 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307652 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007653 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007654 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307655 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
7656 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007657 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7658 out->usecase, PCM_PLAYBACK);
7659 hdlr_stream_cfg.flags = out->flags;
7660 hdlr_stream_cfg.type = PCM_PLAYBACK;
7661 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7662 &hdlr_stream_cfg);
7663 if (ret) {
7664 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7665 out->adsp_hdlr_stream_handle = NULL;
7666 }
7667 }
Gangadhar Sb0210342019-02-22 17:39:41 +05307668 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
7669 is_direct_passthough, false);
7670 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
7671 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007672 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007673 if (ret < 0) {
7674 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7675 out->ip_hdlr_handle = NULL;
7676 }
7677 }
Derek Chenf939fb72018-11-13 13:34:41 -08007678
7679 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7680 calloc(1, sizeof(streams_output_ctxt_t));
7681 if (out_ctxt == NULL) {
7682 ALOGE("%s fail to allocate output ctxt", __func__);
7683 ret = -ENOMEM;
7684 goto error_open;
7685 }
7686 out_ctxt->output = out;
7687
7688 pthread_mutex_lock(&adev->lock);
7689 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7690 pthread_mutex_unlock(&adev->lock);
7691
Eric Laurent994a6932013-07-17 11:51:42 -07007692 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007693 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007694
7695error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307696 if (out->convert_buffer)
7697 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007698 free(out);
7699 *stream_out = NULL;
7700 ALOGD("%s: exit: ret %d", __func__, ret);
7701 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007702}
7703
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307704void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007705 struct audio_stream_out *stream)
7706{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007707 struct stream_out *out = (struct stream_out *)stream;
7708 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007709 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007710
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007711 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307712
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307713 // must deregister from sndmonitor first to prevent races
7714 // between the callback and close_stream
7715 audio_extn_snd_mon_unregister_listener(out);
7716
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007717 /* close adsp hdrl session before standby */
7718 if (out->adsp_hdlr_stream_handle) {
7719 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7720 if (ret)
7721 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7722 out->adsp_hdlr_stream_handle = NULL;
7723 }
7724
Manish Dewangan21a850a2017-08-14 12:03:55 +05307725 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007726 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7727 out->ip_hdlr_handle = NULL;
7728 }
7729
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007730 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307731 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007732 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307733 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307734 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007735 if(ret != 0)
7736 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7737 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007738 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007739 out_standby(&stream->common);
7740
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007741 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007742 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007743 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007744 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007745 if (out->compr_config.codec != NULL)
7746 free(out->compr_config.codec);
7747 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007748
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307749 out->a2dp_compress_mute = false;
7750
Varun Balaraje49253e2017-07-06 19:48:56 +05307751 if (is_interactive_usecase(out->usecase))
7752 free_interactive_usecase(adev, out->usecase);
7753
Ashish Jain83a6cc22016-06-28 14:34:17 +05307754 if (out->convert_buffer != NULL) {
7755 free(out->convert_buffer);
7756 out->convert_buffer = NULL;
7757 }
7758
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007759 if (adev->voice_tx_output == out)
7760 adev->voice_tx_output = NULL;
7761
Aalique Grahame22e49102018-12-18 14:23:57 -08007762 error_log_destroy(out->error_log);
7763 out->error_log = NULL;
7764
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307765 if (adev->primary_output == out)
7766 adev->primary_output = NULL;
7767
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007768 pthread_cond_destroy(&out->cond);
7769 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007770
7771 pthread_mutex_lock(&adev->lock);
7772 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7773 if (out_ctxt != NULL) {
7774 list_remove(&out_ctxt->list);
7775 free(out_ctxt);
7776 } else {
7777 ALOGW("%s, output stream already closed", __func__);
7778 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007779 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007780 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007781 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007782}
7783
7784static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7785{
7786 struct audio_device *adev = (struct audio_device *)dev;
7787 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007788 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007789 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007790 int ret;
7791 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007792 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08007793 struct listnode *node;
7794 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007795
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007796 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007797 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007798
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307799 if (!parms)
7800 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307801
Zhou Songd6d71752019-05-21 18:08:51 +08007802 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307803 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7804 if (ret >= 0) {
7805 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08007806 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307807 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08007808 } else {
7809 ALOGD("sco is off, reset sco and route device to handset/mic");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307810 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08007811 audio_extn_sco_reset_configuration();
7812 list_for_each(node, &adev->usecase_list) {
7813 usecase = node_to_item(node, struct audio_usecase, list);
7814 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
7815 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
7816 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
7817 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
7818 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
7819 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
7820 else
7821 continue;
7822 select_devices(adev, usecase->id);
7823 }
7824 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307825 }
7826
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007827 status = voice_set_parameters(adev, parms);
7828 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007829 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007830
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007831 status = platform_set_parameters(adev->platform, parms);
7832 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007833 goto done;
7834
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007835 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7836 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007837 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007838 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7839 adev->bluetooth_nrec = true;
7840 else
7841 adev->bluetooth_nrec = false;
7842 }
7843
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007844 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7845 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007846 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7847 adev->screen_off = false;
7848 else
7849 adev->screen_off = true;
7850 }
7851
Eric Laurent4b084132018-10-19 17:33:43 -07007852 ret = str_parms_get_int(parms, "rotation", &val);
7853 if (ret >= 0) {
7854 bool reverse_speakers = false;
7855 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
7856 switch (val) {
7857 // FIXME: note that the code below assumes that the speakers are in the correct placement
7858 // relative to the user when the device is rotated 90deg from its default rotation. This
7859 // assumption is device-specific, not platform-specific like this code.
7860 case 270:
7861 reverse_speakers = true;
7862 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
7863 break;
7864 case 0:
7865 case 180:
7866 camera_rotation = CAMERA_ROTATION_PORTRAIT;
7867 break;
7868 case 90:
7869 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
7870 break;
7871 default:
7872 ALOGE("%s: unexpected rotation of %d", __func__, val);
7873 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007874 }
Eric Laurent4b084132018-10-19 17:33:43 -07007875 if (status == 0) {
7876 // check and set swap
7877 // - check if orientation changed and speaker active
7878 // - set rotation and cache the rotation value
7879 adev->camera_orientation =
7880 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
7881 if (!audio_extn_is_maxx_audio_enabled())
7882 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
7883 }
7884 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007885
Mingming Yin514a8bc2014-07-29 15:22:21 -07007886 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7887 if (ret >= 0) {
7888 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7889 adev->bt_wb_speech_enabled = true;
7890 else
7891 adev->bt_wb_speech_enabled = false;
7892 }
7893
Zhou Song12c29502019-03-16 10:37:18 +08007894 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
7895 if (ret >= 0) {
7896 val = atoi(value);
7897 adev->swb_speech_mode = val;
7898 }
7899
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007900 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7901 if (ret >= 0) {
7902 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307903 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007904 if (audio_is_output_device(val) &&
7905 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007906 ALOGV("cache new ext disp type and edid");
7907 ret = platform_get_ext_disp_type(adev->platform);
7908 if (ret < 0) {
7909 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307910 } else {
7911 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007912 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307913 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007914 /*
7915 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7916 * Per AudioPolicyManager, USB device is higher priority than WFD.
7917 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7918 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7919 * starting voice call on USB
7920 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007921 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307922 if (ret >= 0)
7923 audio_extn_usb_add_device(device, atoi(value));
7924
Zhou Song6f862822017-11-06 17:27:57 +08007925 if (!audio_extn_usb_is_tunnel_supported()) {
7926 ALOGV("detected USB connect .. disable proxy");
7927 adev->allow_afe_proxy_usage = false;
7928 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007929 }
7930 }
7931
7932 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7933 if (ret >= 0) {
7934 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307935 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007936 /*
7937 * The HDMI / Displayport disconnect handling has been moved to
7938 * audio extension to ensure that its parameters are not
7939 * invalidated prior to updating sysfs of the disconnect event
7940 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7941 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307942 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007943 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307944 if (ret >= 0)
7945 audio_extn_usb_remove_device(device, atoi(value));
7946
Zhou Song6f862822017-11-06 17:27:57 +08007947 if (!audio_extn_usb_is_tunnel_supported()) {
7948 ALOGV("detected USB disconnect .. enable proxy");
7949 adev->allow_afe_proxy_usage = true;
7950 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007951 }
7952 }
7953
Aalique Grahame22e49102018-12-18 14:23:57 -08007954 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007955 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007956
7957 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007958 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307959 struct audio_usecase *usecase;
7960 struct listnode *node;
7961 list_for_each(node, &adev->usecase_list) {
7962 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05307963 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007964 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307965 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007966
7967 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307968 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007969 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307970 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307971 //force device switch to re configure encoder
7972 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307973 audio_extn_a2dp_set_handoff_mode(false);
7974 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307975 break;
7976 }
7977 }
7978 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007979
7980 //handle vr audio setparam
7981 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7982 value, sizeof(value));
7983 if (ret >= 0) {
7984 ALOGI("Setting vr mode to be %s", value);
7985 if (!strncmp(value, "true", 4)) {
7986 adev->vr_audio_mode_enabled = true;
7987 ALOGI("Setting vr mode to true");
7988 } else if (!strncmp(value, "false", 5)) {
7989 adev->vr_audio_mode_enabled = false;
7990 ALOGI("Setting vr mode to false");
7991 } else {
7992 ALOGI("wrong vr mode set");
7993 }
7994 }
7995
Eric Laurent4b084132018-10-19 17:33:43 -07007996 //FIXME: to be replaced by proper video capture properties API
7997 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
7998 if (ret >= 0) {
7999 int camera_facing = CAMERA_FACING_BACK;
8000 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8001 camera_facing = CAMERA_FACING_FRONT;
8002 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8003 camera_facing = CAMERA_FACING_BACK;
8004 else {
8005 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8006 goto done;
8007 }
8008 adev->camera_orientation =
8009 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8010 struct audio_usecase *usecase;
8011 struct listnode *node;
8012 list_for_each(node, &adev->usecase_list) {
8013 usecase = node_to_item(node, struct audio_usecase, list);
8014 struct stream_in *in = usecase->stream.in;
8015 if (usecase->type == PCM_CAPTURE && in != NULL &&
8016 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8017 select_devices(adev, in->usecase);
8018 }
8019 }
8020 }
8021
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308022 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008023done:
8024 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008025 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308026error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008027 ALOGV("%s: exit with code(%d)", __func__, status);
8028 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008029}
8030
8031static char* adev_get_parameters(const struct audio_hw_device *dev,
8032 const char *keys)
8033{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308034 ALOGD("%s:%s", __func__, keys);
8035
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008036 struct audio_device *adev = (struct audio_device *)dev;
8037 struct str_parms *reply = str_parms_create();
8038 struct str_parms *query = str_parms_create_str(keys);
8039 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308040 char value[256] = {0};
8041 int ret = 0;
8042
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008043 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008044 if (reply) {
8045 str_parms_destroy(reply);
8046 }
8047 if (query) {
8048 str_parms_destroy(query);
8049 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008050 ALOGE("adev_get_parameters: failed to create query or reply");
8051 return NULL;
8052 }
8053
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008054 //handle vr audio getparam
8055
8056 ret = str_parms_get_str(query,
8057 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8058 value, sizeof(value));
8059
8060 if (ret >= 0) {
8061 bool vr_audio_enabled = false;
8062 pthread_mutex_lock(&adev->lock);
8063 vr_audio_enabled = adev->vr_audio_mode_enabled;
8064 pthread_mutex_unlock(&adev->lock);
8065
8066 ALOGI("getting vr mode to %d", vr_audio_enabled);
8067
8068 if (vr_audio_enabled) {
8069 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8070 "true");
8071 goto exit;
8072 } else {
8073 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8074 "false");
8075 goto exit;
8076 }
8077 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008078
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008079 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008080 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008081 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008082 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008083 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308084 pthread_mutex_unlock(&adev->lock);
8085
Naresh Tannirud7205b62014-06-20 02:54:48 +05308086exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008087 str = str_parms_to_str(reply);
8088 str_parms_destroy(query);
8089 str_parms_destroy(reply);
8090
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308091 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008092 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008093}
8094
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008095static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008096{
8097 return 0;
8098}
8099
8100static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8101{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008102 int ret;
8103 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008104
8105 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8106
Haynes Mathew George5191a852013-09-11 14:19:36 -07008107 pthread_mutex_lock(&adev->lock);
8108 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008109 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008110 pthread_mutex_unlock(&adev->lock);
8111 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008112}
8113
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008114static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8115 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008116{
8117 return -ENOSYS;
8118}
8119
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008120static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8121 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008122{
8123 return -ENOSYS;
8124}
8125
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008126static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8127 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008128{
8129 return -ENOSYS;
8130}
8131
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008132static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8133 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008134{
8135 return -ENOSYS;
8136}
8137
8138static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8139{
8140 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008141 struct listnode *node;
8142 struct audio_usecase *usecase = NULL;
8143 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008144
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008145 pthread_mutex_lock(&adev->lock);
8146 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008147 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008148 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008149 if (voice_is_in_call(adev) &&
8150 (mode == AUDIO_MODE_NORMAL ||
8151 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008152 list_for_each(node, &adev->usecase_list) {
8153 usecase = node_to_item(node, struct audio_usecase, list);
8154 if (usecase->type == VOICE_CALL)
8155 break;
8156 }
8157 if (usecase &&
8158 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8159 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8160 true);
8161 if (ret != 0) {
8162 /* default service interval was successfully updated,
8163 reopen USB backend with new service interval */
8164 check_usecases_codec_backend(adev,
8165 usecase,
8166 usecase->out_snd_device);
8167 }
8168 }
8169
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008170 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008171 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008172 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008173 // restore device for other active usecases after stop call
8174 list_for_each(node, &adev->usecase_list) {
8175 usecase = node_to_item(node, struct audio_usecase, list);
8176 select_devices(adev, usecase->id);
8177 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008178 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008179 }
8180 pthread_mutex_unlock(&adev->lock);
8181 return 0;
8182}
8183
8184static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8185{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008186 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008187 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008188
8189 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008190 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008191 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008192
Derek Chend2530072014-11-24 12:39:14 -08008193 if (adev->ext_hw_plugin)
8194 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008195
8196 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008197 pthread_mutex_unlock(&adev->lock);
8198
8199 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008200}
8201
8202static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8203{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008204 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008205 return 0;
8206}
8207
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008208static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008209 const struct audio_config *config)
8210{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008211 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008212
Aalique Grahame22e49102018-12-18 14:23:57 -08008213 /* Don't know if USB HIFI in this context so use true to be conservative */
8214 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8215 true /*is_usb_hifi */) != 0)
8216 return 0;
8217
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008218 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8219 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008220}
8221
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008222static bool adev_input_allow_hifi_record(struct audio_device *adev,
8223 audio_devices_t devices,
8224 audio_input_flags_t flags,
8225 audio_source_t source) {
8226 const bool allowed = true;
8227
8228 if (!audio_is_usb_in_device(devices))
8229 return !allowed;
8230
8231 switch (flags) {
8232 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008233 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008234 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8235 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008236 default:
8237 return !allowed;
8238 }
8239
8240 switch (source) {
8241 case AUDIO_SOURCE_DEFAULT:
8242 case AUDIO_SOURCE_MIC:
8243 case AUDIO_SOURCE_UNPROCESSED:
8244 break;
8245 default:
8246 return !allowed;
8247 }
8248
8249 switch (adev->mode) {
8250 case 0:
8251 break;
8252 default:
8253 return !allowed;
8254 }
8255
8256 return allowed;
8257}
8258
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008259static int adev_update_voice_comm_input_stream(struct stream_in *in,
8260 struct audio_config *config)
8261{
8262 bool valid_rate = (config->sample_rate == 8000 ||
8263 config->sample_rate == 16000 ||
8264 config->sample_rate == 32000 ||
8265 config->sample_rate == 48000);
8266 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8267
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008268 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008269 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008270 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8271 in->config = default_pcm_config_voip_copp;
8272 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8273 DEFAULT_VOIP_BUF_DURATION_MS,
8274 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008275 } else {
8276 ALOGW("%s No valid input in voip, use defaults"
8277 "sample rate %u, channel mask 0x%X",
8278 __func__, config->sample_rate, in->channel_mask);
8279 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008280 in->config.rate = config->sample_rate;
8281 in->sample_rate = config->sample_rate;
8282 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008283 //XXX needed for voice_extn_compress_voip_open_input_stream
8284 in->config.rate = config->sample_rate;
8285 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8286 voice_extn_compress_voip_is_active(in->dev)) &&
8287 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8288 valid_rate && valid_ch) {
8289 voice_extn_compress_voip_open_input_stream(in);
8290 // update rate entries to match config from AF
8291 in->config.rate = config->sample_rate;
8292 in->sample_rate = config->sample_rate;
8293 } else {
8294 ALOGW("%s compress voip not active, use defaults", __func__);
8295 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008296 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008297 return 0;
8298}
8299
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008300static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008301 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008302 audio_devices_t devices,
8303 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008304 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308305 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008306 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008307 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008308{
8309 struct audio_device *adev = (struct audio_device *)dev;
8310 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008311 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008312 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008313 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308314 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008315 bool is_usb_dev = audio_is_usb_in_device(devices);
8316 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8317 devices,
8318 flags,
8319 source);
Andy Hung94320602018-10-29 18:31:12 -07008320 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8321 " sample_rate %u, channel_mask %#x, format %#x",
8322 __func__, flags, is_usb_dev, may_use_hifi_record,
8323 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308324
kunleizdff872d2018-08-20 14:40:33 +08008325 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008326 is_usb_dev = false;
8327 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8328 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8329 __func__, devices);
8330 }
8331
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008332 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008333
8334 if (!(is_usb_dev && may_use_hifi_record)) {
8335 if (config->sample_rate == 0)
8336 config->sample_rate = 48000;
8337 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8338 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8339 if (config->format == AUDIO_FORMAT_DEFAULT)
8340 config->format = AUDIO_FORMAT_PCM_16_BIT;
8341
8342 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8343
Aalique Grahame22e49102018-12-18 14:23:57 -08008344 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8345 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008346 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308347 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008348
8349 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008350
8351 if (!in) {
8352 ALOGE("failed to allocate input stream");
8353 return -ENOMEM;
8354 }
8355
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308356 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308357 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8358 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008359 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008360 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008362 in->stream.common.get_sample_rate = in_get_sample_rate;
8363 in->stream.common.set_sample_rate = in_set_sample_rate;
8364 in->stream.common.get_buffer_size = in_get_buffer_size;
8365 in->stream.common.get_channels = in_get_channels;
8366 in->stream.common.get_format = in_get_format;
8367 in->stream.common.set_format = in_set_format;
8368 in->stream.common.standby = in_standby;
8369 in->stream.common.dump = in_dump;
8370 in->stream.common.set_parameters = in_set_parameters;
8371 in->stream.common.get_parameters = in_get_parameters;
8372 in->stream.common.add_audio_effect = in_add_audio_effect;
8373 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8374 in->stream.set_gain = in_set_gain;
8375 in->stream.read = in_read;
8376 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008377 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308378 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008379 in->stream.set_microphone_direction = in_set_microphone_direction;
8380 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008381 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008382
8383 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008384 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008385 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008386 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008387 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008388 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008389 in->bit_width = 16;
8390 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008391 in->direction = MIC_DIRECTION_UNSPECIFIED;
8392 in->zoom = 0;
Haynes Mathew George46740472017-10-27 18:40:12 -07008393
Andy Hung94320602018-10-29 18:31:12 -07008394 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008395 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8396 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8397 /* Force channel config requested to mono if incall
8398 record is being requested for only uplink/downlink */
8399 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8400 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8401 ret = -EINVAL;
8402 goto err_open;
8403 }
8404 }
8405
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008406 if (is_usb_dev && may_use_hifi_record) {
8407 /* HiFi record selects an appropriate format, channel, rate combo
8408 depending on sink capabilities*/
8409 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8410 &config->format,
8411 &in->supported_formats[0],
8412 MAX_SUPPORTED_FORMATS,
8413 &config->channel_mask,
8414 &in->supported_channel_masks[0],
8415 MAX_SUPPORTED_CHANNEL_MASKS,
8416 &config->sample_rate,
8417 &in->supported_sample_rates[0],
8418 MAX_SUPPORTED_SAMPLE_RATES);
8419 if (ret != 0) {
8420 ret = -EINVAL;
8421 goto err_open;
8422 }
8423 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008424 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308425 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308426 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8427 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8428 in->config.format = PCM_FORMAT_S32_LE;
8429 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308430 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8431 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8432 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8433 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8434 bool ret_error = false;
8435 in->bit_width = 24;
8436 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8437 from HAL is 24_packed and 8_24
8438 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8439 24_packed return error indicating supported format is 24_packed
8440 *> In case of any other source requesting 24 bit or float return error
8441 indicating format supported is 16 bit only.
8442
8443 on error flinger will retry with supported format passed
8444 */
8445 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8446 (source != AUDIO_SOURCE_CAMCORDER)) {
8447 config->format = AUDIO_FORMAT_PCM_16_BIT;
8448 if (config->sample_rate > 48000)
8449 config->sample_rate = 48000;
8450 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008451 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8452 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308453 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8454 ret_error = true;
8455 }
8456
8457 if (ret_error) {
8458 ret = -EINVAL;
8459 goto err_open;
8460 }
8461 }
8462
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008463 in->channel_mask = config->channel_mask;
8464 in->format = config->format;
8465
8466 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308467
8468 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8469 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8470 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8471 else {
8472 ret = -EINVAL;
8473 goto err_open;
8474 }
8475 }
8476
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008477 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8478 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8479 is_low_latency = true;
8480#if LOW_LATENCY_CAPTURE_USE_CASE
8481 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8482#endif
8483 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008484 if (!in->realtime) {
8485 in->config = pcm_config_audio_capture;
8486 frame_size = audio_stream_in_frame_size(&in->stream);
8487 buffer_size = get_input_buffer_size(config->sample_rate,
8488 config->format,
8489 channel_count,
8490 is_low_latency);
8491 in->config.period_size = buffer_size / frame_size;
8492 in->config.rate = config->sample_rate;
8493 in->af_period_multiplier = 1;
8494 } else {
8495 // period size is left untouched for rt mode playback
8496 in->config = pcm_config_audio_capture_rt;
8497 in->af_period_multiplier = af_period_multiplier;
8498 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008499 }
8500
8501 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8502 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8503 in->realtime = 0;
8504 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8505 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008506 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008507 in->stream.start = in_start;
8508 in->stream.stop = in_stop;
8509 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8510 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008511 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8512 } else if (in->realtime) {
8513 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008514 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008515 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008516 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008517 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8518 in->config = pcm_config_audio_capture;
8519 frame_size = audio_stream_in_frame_size(&in->stream);
8520 buffer_size = get_input_buffer_size(config->sample_rate,
8521 config->format,
8522 channel_count,
8523 false /*is_low_latency*/);
8524 in->config.period_size = buffer_size / frame_size;
8525 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008526 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008527 switch (config->format) {
8528 case AUDIO_FORMAT_PCM_32_BIT:
8529 in->bit_width = 32;
8530 break;
8531 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8532 case AUDIO_FORMAT_PCM_8_24_BIT:
8533 in->bit_width = 24;
8534 break;
8535 default:
8536 in->bit_width = 16;
8537 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008538 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308539 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008540 if (config->sample_rate == 0)
8541 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8542 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8543 config->sample_rate != 8000) {
8544 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8545 ret = -EINVAL;
8546 goto err_open;
8547 }
8548 if (config->format == AUDIO_FORMAT_DEFAULT)
8549 config->format = AUDIO_FORMAT_PCM_16_BIT;
8550 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8551 config->format = AUDIO_FORMAT_PCM_16_BIT;
8552 ret = -EINVAL;
8553 goto err_open;
8554 }
8555
8556 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8557 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008558 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008559 in->af_period_multiplier = 1;
8560 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8561 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8562 (config->sample_rate == 8000 ||
8563 config->sample_rate == 16000 ||
8564 config->sample_rate == 32000 ||
8565 config->sample_rate == 48000) &&
8566 channel_count == 1) {
8567 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8568 in->config = pcm_config_audio_capture;
8569 frame_size = audio_stream_in_frame_size(&in->stream);
8570 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8571 config->sample_rate,
8572 config->format,
8573 channel_count, false /*is_low_latency*/);
8574 in->config.period_size = buffer_size / frame_size;
8575 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8576 in->config.rate = config->sample_rate;
8577 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008578 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308579 int ret_val;
8580 pthread_mutex_lock(&adev->lock);
8581 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8582 in, config, &channel_mask_updated);
8583 pthread_mutex_unlock(&adev->lock);
8584
8585 if (!ret_val) {
8586 if (channel_mask_updated == true) {
8587 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8588 __func__, config->channel_mask);
8589 ret = -EINVAL;
8590 goto err_open;
8591 }
8592 ALOGD("%s: created multi-channel session succesfully",__func__);
8593 } else if (audio_extn_compr_cap_enabled() &&
8594 audio_extn_compr_cap_format_supported(config->format) &&
8595 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8596 audio_extn_compr_cap_init(in);
8597 } else if (audio_extn_cin_applicable_stream(in)) {
8598 ret = audio_extn_cin_configure_input_stream(in);
8599 if (ret)
8600 goto err_open;
8601 } else {
8602 in->config = pcm_config_audio_capture;
8603 in->config.rate = config->sample_rate;
8604 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308605 in->format = config->format;
8606 frame_size = audio_stream_in_frame_size(&in->stream);
8607 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008608 config->format,
8609 channel_count,
8610 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008611 /* prevent division-by-zero */
8612 if (frame_size == 0) {
8613 ALOGE("%s: Error frame_size==0", __func__);
8614 ret = -EINVAL;
8615 goto err_open;
8616 }
8617
Revathi Uddarajud2634032017-12-07 14:42:34 +05308618 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008619 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008620
Revathi Uddarajud2634032017-12-07 14:42:34 +05308621 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8622 /* optionally use VOIP usecase depending on config(s) */
8623 ret = adev_update_voice_comm_input_stream(in, config);
8624 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008625
Revathi Uddarajud2634032017-12-07 14:42:34 +05308626 if (ret) {
8627 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8628 goto err_open;
8629 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008630 }
Samyak Jainc37062f2019-04-25 18:41:06 +05308631 if (audio_extn_is_concurrent_capture_enabled()) {
8632 /* Acquire lock to avoid two concurrent use cases initialized to
8633 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08008634
Samyak Jainc37062f2019-04-25 18:41:06 +05308635 if (in->usecase == USECASE_AUDIO_RECORD) {
8636 pthread_mutex_lock(&adev->lock);
8637 if (!(adev->pcm_record_uc_state)) {
8638 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8639 adev->pcm_record_uc_state = 1;
8640 pthread_mutex_unlock(&adev->lock);
8641 } else {
8642 pthread_mutex_unlock(&adev->lock);
8643 /* Assign compress record use case for second record */
8644 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8645 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8646 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8647 if (audio_extn_cin_applicable_stream(in)) {
8648 in->sample_rate = config->sample_rate;
8649 ret = audio_extn_cin_configure_input_stream(in);
8650 if (ret)
8651 goto err_open;
8652 }
8653 }
8654 }
kunleiz28c73e72019-03-27 17:24:04 +08008655 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008656 }
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008657
8658 in->config.channels = channel_count;
8659 in->sample_rate = in->config.rate;
8660
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308661 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8662 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008663 devices, flags, in->format,
8664 in->sample_rate, in->bit_width,
8665 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308666 register_format(in->format, in->supported_formats);
8667 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8668 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308669
Aalique Grahame22e49102018-12-18 14:23:57 -08008670 in->error_log = error_log_create(
8671 ERROR_LOG_ENTRIES,
8672 1000000000 /* aggregate consecutive identical errors within one second */);
8673
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008674 /* This stream could be for sound trigger lab,
8675 get sound trigger pcm if present */
8676 audio_extn_sound_trigger_check_and_get_session(in);
8677
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308678 lock_input_stream(in);
8679 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8680 pthread_mutex_lock(&adev->lock);
8681 in->card_status = adev->card_status;
8682 pthread_mutex_unlock(&adev->lock);
8683 pthread_mutex_unlock(&in->lock);
8684
Aalique Grahame22e49102018-12-18 14:23:57 -08008685 stream_app_type_cfg_init(&in->app_type_cfg);
8686
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008687 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008688
8689 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8690 calloc(1, sizeof(streams_input_ctxt_t));
8691 if (in_ctxt == NULL) {
8692 ALOGE("%s fail to allocate input ctxt", __func__);
8693 ret = -ENOMEM;
8694 goto err_open;
8695 }
8696 in_ctxt->input = in;
8697
8698 pthread_mutex_lock(&adev->lock);
8699 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8700 pthread_mutex_unlock(&adev->lock);
8701
Eric Laurent994a6932013-07-17 11:51:42 -07008702 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008703 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008704
8705err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05308706 if (in->usecase == USECASE_AUDIO_RECORD) {
8707 pthread_mutex_lock(&adev->lock);
8708 adev->pcm_record_uc_state = 0;
8709 pthread_mutex_unlock(&adev->lock);
8710 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008711 free(in);
8712 *stream_in = NULL;
8713 return ret;
8714}
8715
8716static void adev_close_input_stream(struct audio_hw_device *dev,
8717 struct audio_stream_in *stream)
8718{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008719 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008720 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008721 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308722
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308723 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008724
kunleiz70e57612018-12-28 17:50:23 +08008725 /* must deregister from sndmonitor first to prevent races
8726 * between the callback and close_stream
8727 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308728 audio_extn_snd_mon_unregister_listener(stream);
8729
kunleiz70e57612018-12-28 17:50:23 +08008730 /* Disable echo reference if there are no active input, hfp call
8731 * and sound trigger while closing input stream
8732 */
Eric Laurent637e2d42018-11-15 12:24:31 -08008733 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08008734 !audio_extn_hfp_is_active(adev) &&
8735 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008736 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008737 else
8738 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308739
Pallavid7c7a272018-01-16 11:22:55 +05308740 if (in == NULL) {
8741 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8742 return;
8743 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08008744 error_log_destroy(in->error_log);
8745 in->error_log = NULL;
8746
Pallavid7c7a272018-01-16 11:22:55 +05308747
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008748 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308749 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008750 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308751 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008752 if (ret != 0)
8753 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8754 __func__, ret);
8755 } else
8756 in_standby(&stream->common);
8757
Revathi Uddarajud2634032017-12-07 14:42:34 +05308758 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308759 if (in->usecase == USECASE_AUDIO_RECORD) {
8760 adev->pcm_record_uc_state = 0;
8761 }
8762
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008763 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008764 audio_extn_ssr_deinit();
8765 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008766
Garmond Leunge2433c32017-09-28 21:51:22 -07008767 if (audio_extn_ffv_get_stream() == in) {
8768 audio_extn_ffv_stream_deinit();
8769 }
8770
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308771 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008772 audio_extn_compr_cap_format_supported(in->config.format))
8773 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308774
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308775 if (audio_extn_cin_attached_usecase(in->usecase))
8776 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008777
Mingming Yinfd7607b2016-01-22 12:48:44 -08008778 if (in->is_st_session) {
8779 ALOGV("%s: sound trigger pcm stop lab", __func__);
8780 audio_extn_sound_trigger_stop_lab(in);
8781 }
Derek Chenf939fb72018-11-13 13:34:41 -08008782 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8783 if (in_ctxt != NULL) {
8784 list_remove(&in_ctxt->list);
8785 free(in_ctxt);
8786 } else {
8787 ALOGW("%s, input stream already closed", __func__);
8788 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008789 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308790 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008791 return;
8792}
8793
Aalique Grahame22e49102018-12-18 14:23:57 -08008794/* verifies input and output devices and their capabilities.
8795 *
8796 * This verification is required when enabling extended bit-depth or
8797 * sampling rates, as not all qcom products support it.
8798 *
8799 * Suitable for calling only on initialization such as adev_open().
8800 * It fills the audio_device use_case_table[] array.
8801 *
8802 * Has a side-effect that it needs to configure audio routing / devices
8803 * in order to power up the devices and read the device parameters.
8804 * It does not acquire any hw device lock. Should restore the devices
8805 * back to "normal state" upon completion.
8806 */
8807static int adev_verify_devices(struct audio_device *adev)
8808{
8809 /* enumeration is a bit difficult because one really wants to pull
8810 * the use_case, device id, etc from the hidden pcm_device_table[].
8811 * In this case there are the following use cases and device ids.
8812 *
8813 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8814 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8815 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8816 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8817 * [USECASE_AUDIO_RECORD] = {0, 0},
8818 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8819 * [USECASE_VOICE_CALL] = {2, 2},
8820 *
8821 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8822 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8823 */
8824
8825 /* should be the usecases enabled in adev_open_input_stream() */
8826 static const int test_in_usecases[] = {
8827 USECASE_AUDIO_RECORD,
8828 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8829 };
8830 /* should be the usecases enabled in adev_open_output_stream()*/
8831 static const int test_out_usecases[] = {
8832 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8833 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8834 };
8835 static const usecase_type_t usecase_type_by_dir[] = {
8836 PCM_PLAYBACK,
8837 PCM_CAPTURE,
8838 };
8839 static const unsigned flags_by_dir[] = {
8840 PCM_OUT,
8841 PCM_IN,
8842 };
8843
8844 size_t i;
8845 unsigned dir;
8846 const unsigned card_id = adev->snd_card;
8847
8848 for (dir = 0; dir < 2; ++dir) {
8849 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8850 const unsigned flags_dir = flags_by_dir[dir];
8851 const size_t testsize =
8852 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8853 const int *testcases =
8854 dir ? test_in_usecases : test_out_usecases;
8855 const audio_devices_t audio_device =
8856 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8857
8858 for (i = 0; i < testsize; ++i) {
8859 const audio_usecase_t audio_usecase = testcases[i];
8860 int device_id;
8861 struct pcm_params **pparams;
8862 struct stream_out out;
8863 struct stream_in in;
8864 struct audio_usecase uc_info;
8865 int retval;
8866
8867 pparams = &adev->use_case_table[audio_usecase];
8868 pcm_params_free(*pparams); /* can accept null input */
8869 *pparams = NULL;
8870
8871 /* find the device ID for the use case (signed, for error) */
8872 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8873 if (device_id < 0)
8874 continue;
8875
8876 /* prepare structures for device probing */
8877 memset(&uc_info, 0, sizeof(uc_info));
8878 uc_info.id = audio_usecase;
8879 uc_info.type = usecase_type;
8880 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008881 memset(&in, 0, sizeof(in));
8882 in.device = audio_device;
8883 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8884 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08008885 }
8886 memset(&out, 0, sizeof(out));
8887 out.devices = audio_device; /* only field needed in select_devices */
8888 uc_info.stream.out = &out;
8889 uc_info.devices = audio_device;
8890 uc_info.in_snd_device = SND_DEVICE_NONE;
8891 uc_info.out_snd_device = SND_DEVICE_NONE;
8892 list_add_tail(&adev->usecase_list, &uc_info.list);
8893
8894 /* select device - similar to start_(in/out)put_stream() */
8895 retval = select_devices(adev, audio_usecase);
8896 if (retval >= 0) {
8897 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8898#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07008899 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08008900 if (*pparams) {
8901 ALOGV("%s: (%s) card %d device %d", __func__,
8902 dir ? "input" : "output", card_id, device_id);
8903 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8904 } else {
8905 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8906 }
8907#endif
8908 }
8909
8910 /* deselect device - similar to stop_(in/out)put_stream() */
8911 /* 1. Get and set stream specific mixer controls */
8912 retval = disable_audio_route(adev, &uc_info);
8913 /* 2. Disable the rx device */
8914 retval = disable_snd_device(adev,
8915 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8916 list_remove(&uc_info.list);
8917 }
8918 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008919 return 0;
8920}
8921
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308922int adev_create_audio_patch(struct audio_hw_device *dev,
8923 unsigned int num_sources,
8924 const struct audio_port_config *sources,
8925 unsigned int num_sinks,
8926 const struct audio_port_config *sinks,
8927 audio_patch_handle_t *handle)
8928{
Derek Chenf939fb72018-11-13 13:34:41 -08008929 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308930
Derek Chenf939fb72018-11-13 13:34:41 -08008931 ret = audio_extn_hw_loopback_create_audio_patch(dev,
8932 num_sources,
8933 sources,
8934 num_sinks,
8935 sinks,
8936 handle);
8937 ret |= audio_extn_auto_hal_create_audio_patch(dev,
8938 num_sources,
8939 sources,
8940 num_sinks,
8941 sinks,
8942 handle);
8943 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308944}
8945
8946int adev_release_audio_patch(struct audio_hw_device *dev,
8947 audio_patch_handle_t handle)
8948{
Derek Chenf939fb72018-11-13 13:34:41 -08008949 int ret;
8950
8951 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
8952 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
8953 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308954}
8955
8956int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8957{
8958 return audio_extn_hw_loopback_get_audio_port(dev, config);
8959}
8960
8961int adev_set_audio_port_config(struct audio_hw_device *dev,
8962 const struct audio_port_config *config)
8963{
8964 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8965}
8966
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008967static int adev_dump(const audio_hw_device_t *device __unused,
8968 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008969{
8970 return 0;
8971}
8972
8973static int adev_close(hw_device_t *device)
8974{
Aalique Grahame22e49102018-12-18 14:23:57 -08008975 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008976 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008977
8978 if (!adev)
8979 return 0;
8980
8981 pthread_mutex_lock(&adev_init_lock);
8982
8983 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05308984 if (audio_extn_spkr_prot_is_enabled())
8985 audio_extn_spkr_prot_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308986 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008987 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008988 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008989 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008990 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308991 audio_extn_utils_release_streams_cfg_lists(
8992 &adev->streams_output_cfg_list,
8993 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308994 if (audio_extn_qaf_is_enabled())
8995 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008996 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08008997 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07008998 free(adev->snd_dev_ref_cnt);
8999 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009000 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9001 pcm_params_free(adev->use_case_table[i]);
9002 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009003 if (adev->adm_deinit)
9004 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309005 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009006 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309007 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309008 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009009 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309010 if (adev->device_cfg_params) {
9011 free(adev->device_cfg_params);
9012 adev->device_cfg_params = NULL;
9013 }
Derek Chend2530072014-11-24 12:39:14 -08009014 if(adev->ext_hw_plugin)
9015 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009016 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009017 free(device);
9018 adev = NULL;
9019 }
9020 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309021 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009022 return 0;
9023}
9024
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009025/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9026 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9027 * just that it _might_ work.
9028 */
9029static int period_size_is_plausible_for_low_latency(int period_size)
9030{
9031 switch (period_size) {
9032 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009033 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009034 case 240:
9035 case 320:
9036 case 480:
9037 return 1;
9038 default:
9039 return 0;
9040 }
9041}
9042
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309043static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9044{
9045 bool is_snd_card_status = false;
9046 bool is_ext_device_status = false;
9047 char value[32];
9048 int card = -1;
9049 card_status_t status;
9050
9051 if (cookie != adev || !parms)
9052 return;
9053
9054 if (!parse_snd_card_status(parms, &card, &status)) {
9055 is_snd_card_status = true;
9056 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9057 is_ext_device_status = true;
9058 } else {
9059 // not a valid event
9060 return;
9061 }
9062
9063 pthread_mutex_lock(&adev->lock);
9064 if (card == adev->snd_card || is_ext_device_status) {
9065 if (is_snd_card_status && adev->card_status != status) {
9066 adev->card_status = status;
9067 platform_snd_card_update(adev->platform, status);
9068 audio_extn_fm_set_parameters(adev, parms);
9069 } else if (is_ext_device_status) {
9070 platform_set_parameters(adev->platform, parms);
9071 }
9072 }
9073 pthread_mutex_unlock(&adev->lock);
9074 return;
9075}
9076
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309077/* out and adev lock held */
9078static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9079{
9080 struct audio_usecase *uc_info;
9081 float left_p;
9082 float right_p;
9083 audio_devices_t devices;
9084
9085 uc_info = get_usecase_from_list(adev, out->usecase);
9086 if (uc_info == NULL) {
9087 ALOGE("%s: Could not find the usecase (%d) in the list",
9088 __func__, out->usecase);
9089 return -EINVAL;
9090 }
9091
9092 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9093 out->usecase, use_case_table[out->usecase]);
9094
9095 if (restore) {
9096 // restore A2DP device for active usecases and unmute if required
9097 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9098 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9099 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9100 select_devices(adev, uc_info->id);
9101 pthread_mutex_lock(&out->compr_mute_lock);
9102 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9103 (out->a2dp_compress_mute)) {
9104 out->a2dp_compress_mute = false;
9105 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9106 }
9107 pthread_mutex_unlock(&out->compr_mute_lock);
9108 }
9109 } else {
9110 // mute compress stream if suspended
9111 pthread_mutex_lock(&out->compr_mute_lock);
9112 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9113 (!out->a2dp_compress_mute)) {
9114 if (!out->standby) {
9115 ALOGD("%s: selecting speaker and muting stream", __func__);
9116 devices = out->devices;
9117 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9118 left_p = out->volume_l;
9119 right_p = out->volume_r;
9120 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9121 compress_pause(out->compr);
9122 out_set_compr_volume(&out->stream, (float)0, (float)0);
9123 out->a2dp_compress_mute = true;
9124 select_devices(adev, out->usecase);
9125 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9126 compress_resume(out->compr);
9127 out->devices = devices;
9128 out->volume_l = left_p;
9129 out->volume_r = right_p;
9130 }
9131 }
9132 pthread_mutex_unlock(&out->compr_mute_lock);
9133 }
9134 ALOGV("%s: exit", __func__);
9135 return 0;
9136}
9137
9138int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9139{
9140 int ret = 0;
9141
9142 lock_output_stream(out);
9143 pthread_mutex_lock(&adev->lock);
9144
9145 ret = check_a2dp_restore_l(adev, out, restore);
9146
9147 pthread_mutex_unlock(&adev->lock);
9148 pthread_mutex_unlock(&out->lock);
9149 return ret;
9150}
9151
Haynes Mathew George01156f92018-04-13 15:29:54 -07009152void adev_on_battery_status_changed(bool charging)
9153{
9154 pthread_mutex_lock(&adev->lock);
9155 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9156 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009157 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009158 pthread_mutex_unlock(&adev->lock);
9159}
9160
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009161static int adev_open(const hw_module_t *module, const char *name,
9162 hw_device_t **device)
9163{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309164 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009165 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309166 char mixer_ctl_name[128] = {0};
9167 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309168
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009169 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009170 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9171
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009172 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009173 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009174 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009175 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009176 ALOGD("%s: returning existing instance of adev", __func__);
9177 ALOGD("%s: exit", __func__);
9178 pthread_mutex_unlock(&adev_init_lock);
9179 return 0;
9180 }
9181
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009182 adev = calloc(1, sizeof(struct audio_device));
9183
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009184 if (!adev) {
9185 pthread_mutex_unlock(&adev_init_lock);
9186 return -ENOMEM;
9187 }
9188
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009189 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9190
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009191 // register audio ext hidl at the earliest
9192 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309193#ifdef DYNAMIC_LOG_ENABLED
9194 register_for_dynamic_logging("hal");
9195#endif
9196
Derek Chenf939fb72018-11-13 13:34:41 -08009197 /* default audio HAL major version */
9198 uint32_t maj_version = 2;
9199 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9200 maj_version = atoi(value);
9201
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009202 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009203 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009204 adev->device.common.module = (struct hw_module_t *)module;
9205 adev->device.common.close = adev_close;
9206
9207 adev->device.init_check = adev_init_check;
9208 adev->device.set_voice_volume = adev_set_voice_volume;
9209 adev->device.set_master_volume = adev_set_master_volume;
9210 adev->device.get_master_volume = adev_get_master_volume;
9211 adev->device.set_master_mute = adev_set_master_mute;
9212 adev->device.get_master_mute = adev_get_master_mute;
9213 adev->device.set_mode = adev_set_mode;
9214 adev->device.set_mic_mute = adev_set_mic_mute;
9215 adev->device.get_mic_mute = adev_get_mic_mute;
9216 adev->device.set_parameters = adev_set_parameters;
9217 adev->device.get_parameters = adev_get_parameters;
9218 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9219 adev->device.open_output_stream = adev_open_output_stream;
9220 adev->device.close_output_stream = adev_close_output_stream;
9221 adev->device.open_input_stream = adev_open_input_stream;
9222 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309223 adev->device.create_audio_patch = adev_create_audio_patch;
9224 adev->device.release_audio_patch = adev_release_audio_patch;
9225 adev->device.get_audio_port = adev_get_audio_port;
9226 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009227 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309228 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009229
9230 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009231 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009232 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009233 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009234 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009235 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009236 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309237 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009238 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009239 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009240 /* Init audio and voice feature */
9241 audio_extn_feature_init();
9242 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009243 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009244 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009245 list_init(&adev->active_inputs_list);
9246 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009247 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009248 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309249 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309250 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309251 adev->perf_lock_opts[0] = 0x101;
9252 adev->perf_lock_opts[1] = 0x20E;
9253 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009254 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009255 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309256 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009257 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309258
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009259 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009260 adev->platform = platform_init(adev);
9261 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009262 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009263 free(adev->snd_dev_ref_cnt);
9264 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009265 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009266 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9267 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009268 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009269 return -EINVAL;
9270 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009271
Aalique Grahame22e49102018-12-18 14:23:57 -08009272 adev->extspk = audio_extn_extspk_init(adev);
9273
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309274 if (audio_extn_qaf_is_enabled()) {
9275 ret = audio_extn_qaf_init(adev);
9276 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009277 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309278 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009279 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309280 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9281 *device = NULL;
9282 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309283 return ret;
9284 }
9285
9286 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9287 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9288 }
9289
Derek Chenae7b0342019-02-08 15:17:04 -08009290 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009291 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9292
Eric Laurentc4aef752013-09-12 17:45:53 -07009293 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9294 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9295 if (adev->visualizer_lib == NULL) {
9296 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9297 } else {
9298 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9299 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009300 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009301 "visualizer_hal_start_output");
9302 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009303 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009304 "visualizer_hal_stop_output");
9305 }
9306 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309307 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009308 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009309 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009310 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309311 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009312 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009313
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009314 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9315 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9316 if (adev->offload_effects_lib == NULL) {
9317 ALOGE("%s: DLOPEN failed for %s", __func__,
9318 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9319 } else {
9320 ALOGV("%s: DLOPEN successful for %s", __func__,
9321 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9322 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309323 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009324 "offload_effects_bundle_hal_start_output");
9325 adev->offload_effects_stop_output =
9326 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9327 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009328 adev->offload_effects_set_hpx_state =
9329 (int (*)(bool))dlsym(adev->offload_effects_lib,
9330 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309331 adev->offload_effects_get_parameters =
9332 (void (*)(struct str_parms *, struct str_parms *))
9333 dlsym(adev->offload_effects_lib,
9334 "offload_effects_bundle_get_parameters");
9335 adev->offload_effects_set_parameters =
9336 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9337 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009338 }
9339 }
9340
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009341 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9342 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9343 if (adev->adm_lib == NULL) {
9344 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9345 } else {
9346 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9347 adev->adm_init = (adm_init_t)
9348 dlsym(adev->adm_lib, "adm_init");
9349 adev->adm_deinit = (adm_deinit_t)
9350 dlsym(adev->adm_lib, "adm_deinit");
9351 adev->adm_register_input_stream = (adm_register_input_stream_t)
9352 dlsym(adev->adm_lib, "adm_register_input_stream");
9353 adev->adm_register_output_stream = (adm_register_output_stream_t)
9354 dlsym(adev->adm_lib, "adm_register_output_stream");
9355 adev->adm_deregister_stream = (adm_deregister_stream_t)
9356 dlsym(adev->adm_lib, "adm_deregister_stream");
9357 adev->adm_request_focus = (adm_request_focus_t)
9358 dlsym(adev->adm_lib, "adm_request_focus");
9359 adev->adm_abandon_focus = (adm_abandon_focus_t)
9360 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009361 adev->adm_set_config = (adm_set_config_t)
9362 dlsym(adev->adm_lib, "adm_set_config");
9363 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9364 dlsym(adev->adm_lib, "adm_request_focus_v2");
9365 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9366 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9367 adev->adm_on_routing_change = (adm_on_routing_change_t)
9368 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009369 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9370 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009371 }
9372 }
9373
Aalique Grahame22e49102018-12-18 14:23:57 -08009374 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009375 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009376 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009377 //initialize this to false for now,
9378 //this will be set to true through set param
9379 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009380
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009381 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009382 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009383
9384 if (k_enable_extended_precision)
9385 adev_verify_devices(adev);
9386
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009387 adev->dsp_bit_width_enforce_mode =
9388 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009389
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309390 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9391 &adev->streams_output_cfg_list,
9392 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009393
Kiran Kandi910e1862013-10-29 13:29:42 -07009394 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009395
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009396 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009397 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9398 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009399 trial = atoi(value);
9400 if (period_size_is_plausible_for_low_latency(trial)) {
9401 pcm_config_low_latency.period_size = trial;
9402 pcm_config_low_latency.start_threshold = trial / 4;
9403 pcm_config_low_latency.avail_min = trial / 4;
9404 configured_low_latency_capture_period_size = trial;
9405 }
9406 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009407 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9408 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009409 trial = atoi(value);
9410 if (period_size_is_plausible_for_low_latency(trial)) {
9411 configured_low_latency_capture_period_size = trial;
9412 }
9413 }
9414
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009415 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9416
Eric Laurent4b084132018-10-19 17:33:43 -07009417 adev->camera_orientation = CAMERA_DEFAULT;
9418
Aalique Grahame22e49102018-12-18 14:23:57 -08009419 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9420 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009421 af_period_multiplier = atoi(value);
9422 if (af_period_multiplier < 0)
9423 af_period_multiplier = 2;
9424 else if (af_period_multiplier > 4)
9425 af_period_multiplier = 4;
9426
9427 ALOGV("new period_multiplier = %d", af_period_multiplier);
9428 }
9429
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009430 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009431
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009432 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009433 pthread_mutex_unlock(&adev_init_lock);
9434
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009435 if (adev->adm_init)
9436 adev->adm_data = adev->adm_init();
9437
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309438 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309439 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009440 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309441
9442 audio_extn_snd_mon_init();
9443 pthread_mutex_lock(&adev->lock);
9444 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9445 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009446 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9447 /*
9448 * if the battery state callback happens before charging can be queried,
9449 * it will be guarded with the adev->lock held in the cb function and so
9450 * the callback value will reflect the latest state
9451 */
9452 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309453 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009454 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009455 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009456 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309457 /* Allocate memory for Device config params */
9458 adev->device_cfg_params = (struct audio_device_config_param*)
9459 calloc(platform_get_max_codec_backend(),
9460 sizeof(struct audio_device_config_param));
9461 if (adev->device_cfg_params == NULL)
9462 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309463
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309464 /*
9465 * Check if new PSPD matrix mixer control is supported. If not
9466 * supported, then set flag so that old mixer ctrl is sent while
9467 * sending pspd coefficients on older kernel version. Query mixer
9468 * control for default pcm id and channel value one.
9469 */
9470 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9471 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9472
9473 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9474 if (!ctl) {
9475 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9476 __func__, mixer_ctl_name);
9477 adev->use_old_pspd_mix_ctrl = true;
9478 }
9479
Eric Laurent994a6932013-07-17 11:51:42 -07009480 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009481 return 0;
9482}
9483
9484static struct hw_module_methods_t hal_module_methods = {
9485 .open = adev_open,
9486};
9487
9488struct audio_module HAL_MODULE_INFO_SYM = {
9489 .common = {
9490 .tag = HARDWARE_MODULE_TAG,
9491 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9492 .hal_api_version = HARDWARE_HAL_API_VERSION,
9493 .id = AUDIO_HARDWARE_MODULE_ID,
9494 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009495 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009496 .methods = &hal_module_methods,
9497 },
9498};