blob: 434ece88813305b0d35912d540ff33c936644f59 [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080072#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -070096#define INVALID_OUT_VOLUME -1
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070097
Aalique Grahame22e49102018-12-18 14:23:57 -080098#define RECORD_GAIN_MIN 0.0f
99#define RECORD_GAIN_MAX 1.0f
100#define RECORD_VOLUME_CTL_MAX 0x2000
101
102/* treat as unsigned Q1.13 */
103#define APP_TYPE_GAIN_DEFAULT 0x2000
104
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700105#define PROXY_OPEN_RETRY_COUNT 100
106#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800107
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800108#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
109 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
110 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
111#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
112 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800113
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700114#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700115#define DEFAULT_VOIP_BUF_DURATION_MS 20
116#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
117#define DEFAULT_VOIP_SAMP_RATE 48000
118
119#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
120
121struct pcm_config default_pcm_config_voip_copp = {
122 .channels = 1,
123 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
124 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
125 .period_count = 2,
126 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800127 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
128 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700129};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700130
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700131#define MIN_CHANNEL_COUNT 1
132#define DEFAULT_CHANNEL_COUNT 2
133#define MAX_HIFI_CHANNEL_COUNT 8
134
Aalique Grahame22e49102018-12-18 14:23:57 -0800135#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
136#define MAX_CHANNEL_COUNT 1
137#else
138#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
139#define XSTR(x) STR(x)
140#define STR(x) #x
141#endif
142
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700143static unsigned int configured_low_latency_capture_period_size =
144 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
145
Haynes Mathew George16081042017-05-31 17:16:49 -0700146#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
147#define MMAP_PERIOD_COUNT_MIN 32
148#define MMAP_PERIOD_COUNT_MAX 512
149#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
150
Aalique Grahame22e49102018-12-18 14:23:57 -0800151/* This constant enables extended precision handling.
152 * TODO The flag is off until more testing is done.
153 */
154static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700155extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800156
Eric Laurentb23d5282013-05-14 15:27:20 -0700157struct pcm_config pcm_config_deep_buffer = {
158 .channels = 2,
159 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
160 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
161 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
162 .format = PCM_FORMAT_S16_LE,
163 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
164 .stop_threshold = INT_MAX,
165 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
166};
167
168struct pcm_config pcm_config_low_latency = {
169 .channels = 2,
170 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
171 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
172 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
173 .format = PCM_FORMAT_S16_LE,
174 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
175 .stop_threshold = INT_MAX,
176 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
177};
178
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800179struct pcm_config pcm_config_haptics_audio = {
180 .channels = 1,
181 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
182 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
183 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
184 .format = PCM_FORMAT_S16_LE,
185 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
186 .stop_threshold = INT_MAX,
187 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
188};
189
190struct pcm_config pcm_config_haptics = {
191 .channels = 1,
192 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
193 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
194 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
195 .format = PCM_FORMAT_S16_LE,
196 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
197 .stop_threshold = INT_MAX,
198 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
199};
200
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700201static int af_period_multiplier = 4;
202struct pcm_config pcm_config_rt = {
203 .channels = 2,
204 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
205 .period_size = ULL_PERIOD_SIZE, //1 ms
206 .period_count = 512, //=> buffer size is 512ms
207 .format = PCM_FORMAT_S16_LE,
208 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
209 .stop_threshold = INT_MAX,
210 .silence_threshold = 0,
211 .silence_size = 0,
212 .avail_min = ULL_PERIOD_SIZE, //1 ms
213};
214
Eric Laurentb23d5282013-05-14 15:27:20 -0700215struct pcm_config pcm_config_hdmi_multi = {
216 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
217 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
218 .period_size = HDMI_MULTI_PERIOD_SIZE,
219 .period_count = HDMI_MULTI_PERIOD_COUNT,
220 .format = PCM_FORMAT_S16_LE,
221 .start_threshold = 0,
222 .stop_threshold = INT_MAX,
223 .avail_min = 0,
224};
225
Haynes Mathew George16081042017-05-31 17:16:49 -0700226struct pcm_config pcm_config_mmap_playback = {
227 .channels = 2,
228 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
229 .period_size = MMAP_PERIOD_SIZE,
230 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
231 .format = PCM_FORMAT_S16_LE,
232 .start_threshold = MMAP_PERIOD_SIZE*8,
233 .stop_threshold = INT32_MAX,
234 .silence_threshold = 0,
235 .silence_size = 0,
236 .avail_min = MMAP_PERIOD_SIZE, //1 ms
237};
238
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700239struct pcm_config pcm_config_hifi = {
240 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
241 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
242 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
243 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
244 .format = PCM_FORMAT_S24_3LE,
245 .start_threshold = 0,
246 .stop_threshold = INT_MAX,
247 .avail_min = 0,
248};
249
Eric Laurentb23d5282013-05-14 15:27:20 -0700250struct pcm_config pcm_config_audio_capture = {
251 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700252 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
253 .format = PCM_FORMAT_S16_LE,
254};
255
Haynes Mathew George16081042017-05-31 17:16:49 -0700256struct pcm_config pcm_config_mmap_capture = {
257 .channels = 2,
258 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
259 .period_size = MMAP_PERIOD_SIZE,
260 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
261 .format = PCM_FORMAT_S16_LE,
262 .start_threshold = 0,
263 .stop_threshold = INT_MAX,
264 .silence_threshold = 0,
265 .silence_size = 0,
266 .avail_min = MMAP_PERIOD_SIZE, //1 ms
267};
268
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700269#define AFE_PROXY_CHANNEL_COUNT 2
270#define AFE_PROXY_SAMPLING_RATE 48000
271
272#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
273#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
274
275struct pcm_config pcm_config_afe_proxy_playback = {
276 .channels = AFE_PROXY_CHANNEL_COUNT,
277 .rate = AFE_PROXY_SAMPLING_RATE,
278 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
279 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
280 .format = PCM_FORMAT_S16_LE,
281 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
282 .stop_threshold = INT_MAX,
283 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
284};
285
286#define AFE_PROXY_RECORD_PERIOD_SIZE 768
287#define AFE_PROXY_RECORD_PERIOD_COUNT 4
288
Aalique Grahame22e49102018-12-18 14:23:57 -0800289struct pcm_config pcm_config_audio_capture_rt = {
290 .channels = 2,
291 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
292 .period_size = ULL_PERIOD_SIZE,
293 .period_count = 512,
294 .format = PCM_FORMAT_S16_LE,
295 .start_threshold = 0,
296 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
297 .silence_threshold = 0,
298 .silence_size = 0,
299 .avail_min = ULL_PERIOD_SIZE, //1 ms
300};
301
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700302struct pcm_config pcm_config_afe_proxy_record = {
303 .channels = AFE_PROXY_CHANNEL_COUNT,
304 .rate = AFE_PROXY_SAMPLING_RATE,
305 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
306 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
307 .format = PCM_FORMAT_S16_LE,
308 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
309 .stop_threshold = INT_MAX,
310 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
311};
312
Ashish Jainf1eaa582016-05-23 20:54:24 +0530313#define AUDIO_MAX_PCM_FORMATS 7
314
315const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
316 [AUDIO_FORMAT_DEFAULT] = 0,
317 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
318 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
319 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
320 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
321 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
322 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
323};
324
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800325const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700326 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
327 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800328 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700329 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
330 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700331 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700332 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700333 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
334 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
340 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700341 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
342 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700343 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800344 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700345
Eric Laurentb23d5282013-05-14 15:27:20 -0700346 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700347 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530348 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
349 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
350 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530351 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
352 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700353 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700354 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700355 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700356 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700357
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800358 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800359 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700360 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700361
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700362 [USECASE_VOICE2_CALL] = "voice2-call",
363 [USECASE_VOLTE_CALL] = "volte-call",
364 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800365 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800366 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
367 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800368 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700369 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
370 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
371 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800372 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
373 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
374 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
375
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700376 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
377 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700378 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
379 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700380
381 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
382 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530383 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700384
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530385 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530386 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
387 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700388
389 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
390 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530391 /* For Interactive Audio Streams */
392 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
399 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700400
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800401 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
402
Derek Chenf6318be2017-06-12 17:16:24 -0400403 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
404
405 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
406 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
407 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
408 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700409};
410
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700411static const audio_usecase_t offload_usecases[] = {
412 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700413 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
414 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
415 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
416 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
417 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
418 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
419 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
420 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700421};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800422
Varun Balaraje49253e2017-07-06 19:48:56 +0530423static const audio_usecase_t interactive_usecases[] = {
424 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
426 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
427 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
428 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
429 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
431 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
432};
433
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800434#define STRING_TO_ENUM(string) { #string, string }
435
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800436struct string_to_enum {
437 const char *name;
438 uint32_t value;
439};
440
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700441static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800442 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
444 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
445 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700446 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800447 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800449 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700450 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
451 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
452 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
453 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
455 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
456 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
457 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
458 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
460 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800461};
462
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700463static const struct string_to_enum formats_name_to_enum_table[] = {
464 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
465 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
466 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700467 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
468 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
469 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700470 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800471 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
472 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700473 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800474};
475
476//list of all supported sample rates by HDMI specification.
477static const int out_hdmi_sample_rates[] = {
478 32000, 44100, 48000, 88200, 96000, 176400, 192000,
479};
480
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700481static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800482 STRING_TO_ENUM(32000),
483 STRING_TO_ENUM(44100),
484 STRING_TO_ENUM(48000),
485 STRING_TO_ENUM(88200),
486 STRING_TO_ENUM(96000),
487 STRING_TO_ENUM(176400),
488 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700489};
490
Carter Hsu2e429db2019-05-14 18:50:52 +0800491struct in_effect_list {
492 struct listnode list;
493 effect_handle_t handle;
494};
495
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700496static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700497static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700498static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700499//cache last MBDRC cal step level
500static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700501
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530502static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
503static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700504static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800505static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530506static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530507
Vatsal Buchac09ae062018-11-14 13:25:08 +0530508#ifdef AUDIO_FEATURE_ENABLED_GCOV
509extern void __gcov_flush();
510static void enable_gcov()
511{
512 __gcov_flush();
513}
514#else
515static void enable_gcov()
516{
517}
518#endif
519
justinweng20fb6d82019-02-21 18:49:00 -0700520static int in_set_microphone_direction(const struct audio_stream_in *stream,
521 audio_microphone_direction_t dir);
522static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
523
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700524static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
525 int flags __unused)
526{
527 int dir = 0;
528 switch (uc_id) {
529 case USECASE_AUDIO_RECORD_LOW_LATENCY:
530 dir = 1;
531 case USECASE_AUDIO_PLAYBACK_ULL:
532 break;
533 default:
534 return false;
535 }
536
537 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
538 PCM_PLAYBACK : PCM_CAPTURE);
539 if (adev->adm_is_noirq_avail)
540 return adev->adm_is_noirq_avail(adev->adm_data,
541 adev->snd_card, dev_id, dir);
542 return false;
543}
544
545static void register_out_stream(struct stream_out *out)
546{
547 struct audio_device *adev = out->dev;
548 if (is_offload_usecase(out->usecase) ||
549 !adev->adm_register_output_stream)
550 return;
551
552 // register stream first for backward compatibility
553 adev->adm_register_output_stream(adev->adm_data,
554 out->handle,
555 out->flags);
556
557 if (!adev->adm_set_config)
558 return;
559
560 if (out->realtime)
561 adev->adm_set_config(adev->adm_data,
562 out->handle,
563 out->pcm, &out->config);
564}
565
566static void register_in_stream(struct stream_in *in)
567{
568 struct audio_device *adev = in->dev;
569 if (!adev->adm_register_input_stream)
570 return;
571
572 adev->adm_register_input_stream(adev->adm_data,
573 in->capture_handle,
574 in->flags);
575
576 if (!adev->adm_set_config)
577 return;
578
579 if (in->realtime)
580 adev->adm_set_config(adev->adm_data,
581 in->capture_handle,
582 in->pcm,
583 &in->config);
584}
585
586static void request_out_focus(struct stream_out *out, long ns)
587{
588 struct audio_device *adev = out->dev;
589
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700590 if (adev->adm_request_focus_v2)
591 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
592 else if (adev->adm_request_focus)
593 adev->adm_request_focus(adev->adm_data, out->handle);
594}
595
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700596static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700597{
598 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700599 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700600
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700601 if (adev->adm_request_focus_v2_1)
602 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
603 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700604 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
605 else if (adev->adm_request_focus)
606 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700607
608 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700609}
610
611static void release_out_focus(struct stream_out *out)
612{
613 struct audio_device *adev = out->dev;
614
615 if (adev->adm_abandon_focus)
616 adev->adm_abandon_focus(adev->adm_data, out->handle);
617}
618
619static void release_in_focus(struct stream_in *in)
620{
621 struct audio_device *adev = in->dev;
622 if (adev->adm_abandon_focus)
623 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
624}
625
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530626static int parse_snd_card_status(struct str_parms *parms, int *card,
627 card_status_t *status)
628{
629 char value[32]={0};
630 char state[32]={0};
631
632 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
633 if (ret < 0)
634 return -1;
635
636 // sscanf should be okay as value is of max length 32.
637 // same as sizeof state.
638 if (sscanf(value, "%d,%s", card, state) < 2)
639 return -1;
640
641 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
642 CARD_STATUS_OFFLINE;
643 return 0;
644}
645
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700646static inline void adjust_frames_for_device_delay(struct stream_out *out,
647 uint32_t *dsp_frames) {
648 // Adjustment accounts for A2dp encoder latency with offload usecases
649 // Note: Encoder latency is returned in ms.
650 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
651 unsigned long offset =
652 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
653 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
654 }
655}
656
vivek mehtaa76401a2015-04-24 14:12:15 -0700657__attribute__ ((visibility ("default")))
658bool audio_hw_send_gain_dep_calibration(int level) {
659 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700660 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700661
662 pthread_mutex_lock(&adev_init_lock);
663
664 if (adev != NULL && adev->platform != NULL) {
665 pthread_mutex_lock(&adev->lock);
666 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700667
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530668 // cache level info for any of the use case which
669 // was not started.
670 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700671
vivek mehtaa76401a2015-04-24 14:12:15 -0700672 pthread_mutex_unlock(&adev->lock);
673 } else {
674 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
675 }
676
677 pthread_mutex_unlock(&adev_init_lock);
678
679 return ret_val;
680}
681
Ashish Jain5106d362016-05-11 19:23:33 +0530682static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
683{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800684 bool gapless_enabled = false;
685 const char *mixer_ctl_name = "Compress Gapless Playback";
686 struct mixer_ctl *ctl;
687
688 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700689 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530690
691 /*Disable gapless if its AV playback*/
692 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800693
694 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
695 if (!ctl) {
696 ALOGE("%s: Could not get ctl for mixer cmd - %s",
697 __func__, mixer_ctl_name);
698 return -EINVAL;
699 }
700
701 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
702 ALOGE("%s: Could not set gapless mode %d",
703 __func__, gapless_enabled);
704 return -EINVAL;
705 }
706 return 0;
707}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700708
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700709__attribute__ ((visibility ("default")))
710int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
711 int table_size) {
712 int ret_val = 0;
713 ALOGV("%s: enter ... ", __func__);
714
715 pthread_mutex_lock(&adev_init_lock);
716 if (adev == NULL) {
717 ALOGW("%s: adev is NULL .... ", __func__);
718 goto done;
719 }
720
721 pthread_mutex_lock(&adev->lock);
722 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
723 pthread_mutex_unlock(&adev->lock);
724done:
725 pthread_mutex_unlock(&adev_init_lock);
726 ALOGV("%s: exit ... ", __func__);
727 return ret_val;
728}
729
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800730bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800731{
732 bool ret = false;
733 ALOGV("%s: enter ...", __func__);
734
735 pthread_mutex_lock(&adev_init_lock);
736
737 if (adev != NULL && adev->platform != NULL) {
738 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800739 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800740 pthread_mutex_unlock(&adev->lock);
741 }
742
743 pthread_mutex_unlock(&adev_init_lock);
744
745 ALOGV("%s: exit with ret %d", __func__, ret);
746 return ret;
747}
Aalique Grahame22e49102018-12-18 14:23:57 -0800748
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700749static bool is_supported_format(audio_format_t format)
750{
Eric Laurent86e17132013-09-12 17:49:30 -0700751 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530752 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530753 format == AUDIO_FORMAT_AAC_LC ||
754 format == AUDIO_FORMAT_AAC_HE_V1 ||
755 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530756 format == AUDIO_FORMAT_AAC_ADTS_LC ||
757 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
758 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530759 format == AUDIO_FORMAT_AAC_LATM_LC ||
760 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
761 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530762 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
763 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530764 format == AUDIO_FORMAT_PCM_FLOAT ||
765 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700766 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530767 format == AUDIO_FORMAT_AC3 ||
768 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700769 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530770 format == AUDIO_FORMAT_DTS ||
771 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800772 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530773 format == AUDIO_FORMAT_ALAC ||
774 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530775 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530776 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800777 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530778 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700779 format == AUDIO_FORMAT_APTX ||
780 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800781 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700782
783 return false;
784}
785
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700786static inline bool is_mmap_usecase(audio_usecase_t uc_id)
787{
788 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
789 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
790}
791
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700792static inline bool is_valid_volume(float left, float right)
793{
794 return ((left >= 0.0f && right >= 0.0f) ? true : false);
795}
796
Avinash Vaish71a8b972014-07-24 15:36:33 +0530797static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
798 struct audio_usecase *uc_info)
799{
800 struct listnode *node;
801 struct audio_usecase *usecase;
802
803 if (uc_info == NULL)
804 return -EINVAL;
805
806 /* Re-route all voice usecases on the shared backend other than the
807 specified usecase to new snd devices */
808 list_for_each(node, &adev->usecase_list) {
809 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800810 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530811 enable_audio_route(adev, usecase);
812 }
813 return 0;
814}
815
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530816static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530817{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530818 ALOGV("%s", __func__);
819 audio_route_apply_and_update_path(adev->audio_route,
820 "asrc-mode");
821 adev->asrc_mode_enabled = true;
822}
823
824static void disable_asrc_mode(struct audio_device *adev)
825{
826 ALOGV("%s", __func__);
827 audio_route_reset_and_update_path(adev->audio_route,
828 "asrc-mode");
829 adev->asrc_mode_enabled = false;
830}
831
832/*
833 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
834 * 44.1 or Native DSD backends are enabled for any of current use case.
835 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
836 * - Disable current mix path use case(Headphone backend) and re-enable it with
837 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
838 * e.g. Naitve DSD or Headphone 44.1 -> + 48
839 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530840static void check_and_set_asrc_mode(struct audio_device *adev,
841 struct audio_usecase *uc_info,
842 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530843{
844 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530845 int i, num_new_devices = 0;
846 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
847 /*
848 *Split snd device for new combo use case
849 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
850 */
851 if (platform_split_snd_device(adev->platform,
852 snd_device,
853 &num_new_devices,
854 split_new_snd_devices) == 0) {
855 for (i = 0; i < num_new_devices; i++)
856 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
857 } else {
858 int new_backend_idx = platform_get_backend_index(snd_device);
859 if (((new_backend_idx == HEADPHONE_BACKEND) ||
860 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
861 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
862 !adev->asrc_mode_enabled) {
863 struct listnode *node = NULL;
864 struct audio_usecase *uc = NULL;
865 struct stream_out *curr_out = NULL;
866 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
867 int i, num_devices, ret = 0;
868 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530869
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530870 list_for_each(node, &adev->usecase_list) {
871 uc = node_to_item(node, struct audio_usecase, list);
872 curr_out = (struct stream_out*) uc->stream.out;
873 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
874 /*
875 *Split snd device for existing combo use case
876 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
877 */
878 ret = platform_split_snd_device(adev->platform,
879 uc->out_snd_device,
880 &num_devices,
881 split_snd_devices);
882 if (ret < 0 || num_devices == 0) {
883 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
884 split_snd_devices[0] = uc->out_snd_device;
885 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800886 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530887 for (i = 0; i < num_devices; i++) {
888 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
889 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
890 if((new_backend_idx == HEADPHONE_BACKEND) &&
891 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
892 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
893 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
894 __func__);
895 enable_asrc_mode(adev);
896 break;
897 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
898 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
899 (usecase_backend_idx == HEADPHONE_BACKEND)) {
900 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
901 __func__);
902 disable_audio_route(adev, uc);
903 disable_snd_device(adev, uc->out_snd_device);
904 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
905 if (new_backend_idx == DSD_NATIVE_BACKEND)
906 audio_route_apply_and_update_path(adev->audio_route,
907 "hph-true-highquality-mode");
908 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
909 (curr_out->bit_width >= 24))
910 audio_route_apply_and_update_path(adev->audio_route,
911 "hph-highquality-mode");
912 enable_asrc_mode(adev);
913 enable_snd_device(adev, uc->out_snd_device);
914 enable_audio_route(adev, uc);
915 break;
916 }
917 }
918 // reset split devices count
919 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800920 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530921 if (adev->asrc_mode_enabled)
922 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530923 }
924 }
925 }
926}
927
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700928static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
929 struct audio_effect_config effect_config,
930 unsigned int param_value)
931{
932 char mixer_ctl_name[] = "Audio Effect";
933 struct mixer_ctl *ctl;
934 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800935 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700936
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700937 if (in == NULL) {
938 ALOGE("%s: active input stream is NULL", __func__);
939 return -EINVAL;
940 }
941
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700942 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
943 if (!ctl) {
944 ALOGE("%s: Could not get mixer ctl - %s",
945 __func__, mixer_ctl_name);
946 return -EINVAL;
947 }
948
949 set_values[0] = 1; //0:Rx 1:Tx
950 set_values[1] = in->app_type_cfg.app_type;
951 set_values[2] = (long)effect_config.module_id;
952 set_values[3] = (long)effect_config.instance_id;
953 set_values[4] = (long)effect_config.param_id;
954 set_values[5] = param_value;
955
956 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
957
958 return 0;
959
960}
961
962static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
963 int effect_type, unsigned int *param_value)
964{
965 int ret = 0;
966 struct audio_effect_config other_effect_config;
967 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800968 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700969
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700970 if (in == NULL) {
971 ALOGE("%s: active input stream is NULL", __func__);
972 return -EINVAL;
973 }
974
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700975 usecase = get_usecase_from_list(adev, in->usecase);
976 if (!usecase)
977 return -EINVAL;
978
979 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
980 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
981 if (ret < 0) {
982 ALOGE("%s Failed to get effect params %d", __func__, ret);
983 return ret;
984 }
985
986 if (module_id == other_effect_config.module_id) {
987 //Same module id for AEC/NS. Values need to be combined
988 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
989 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
990 *param_value |= other_effect_config.param_value;
991 }
992 }
993
994 return ret;
995}
996
997static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +0530998{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700999 struct audio_effect_config effect_config;
1000 struct audio_usecase *usecase = NULL;
1001 int ret = 0;
1002 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -08001003 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001004
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001005 if(!voice_extn_is_dynamic_ecns_enabled())
1006 return ENOSYS;
1007
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001008 if (!in) {
1009 ALOGE("%s: Invalid input stream", __func__);
1010 return -EINVAL;
1011 }
1012
1013 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1014
1015 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001016 if (usecase == NULL) {
1017 ALOGE("%s: Could not find the usecase (%d) in the list",
1018 __func__, in->usecase);
1019 return -EINVAL;
1020 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001021
1022 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1023 if (ret < 0) {
1024 ALOGE("%s Failed to get module id %d", __func__, ret);
1025 return ret;
1026 }
1027 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1028 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1029
1030 if(enable)
1031 param_value = effect_config.param_value;
1032
1033 /*Special handling for AEC & NS effects Param values need to be
1034 updated if module ids are same*/
1035
1036 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1037 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1038 if (ret < 0)
1039 return ret;
1040 }
1041
1042 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1043
1044 return ret;
1045}
1046
1047static void check_and_enable_effect(struct audio_device *adev)
1048{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001049 if(!voice_extn_is_dynamic_ecns_enabled())
1050 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001051
Eric Laurent637e2d42018-11-15 12:24:31 -08001052 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001053
Eric Laurent637e2d42018-11-15 12:24:31 -08001054 if (in != NULL && !in->standby) {
1055 if (in->enable_aec)
1056 enable_disable_effect(adev, EFFECT_AEC, true);
1057
1058 if (in->enable_ns &&
1059 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1060 enable_disable_effect(adev, EFFECT_NS, true);
1061 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001062 }
1063}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001064
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001065int pcm_ioctl(struct pcm *pcm, int request, ...)
1066{
1067 va_list ap;
1068 void * arg;
1069 int pcm_fd = *(int*)pcm;
1070
1071 va_start(ap, request);
1072 arg = va_arg(ap, void *);
1073 va_end(ap);
1074
1075 return ioctl(pcm_fd, request, arg);
1076}
1077
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001078int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001079 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001080{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001081 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001082 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301083 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301084 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001085
1086 if (usecase == NULL)
1087 return -EINVAL;
1088
1089 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1090
Carter Hsu2e429db2019-05-14 18:50:52 +08001091 if (usecase->type == PCM_CAPTURE) {
1092 struct stream_in *in = usecase->stream.in;
1093 struct audio_usecase *uinfo;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001094 snd_device = usecase->in_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001095
1096 if (in) {
1097 if (in->enable_aec || in->enable_ec_port) {
1098 audio_devices_t out_device = AUDIO_DEVICE_OUT_SPEAKER;
1099 struct listnode *node;
1100 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
1101 USECASE_AUDIO_PLAYBACK_VOIP);
1102 if (voip_usecase) {
1103 out_device = voip_usecase->stream.out->devices;
1104 } else if (adev->primary_output &&
1105 !adev->primary_output->standby) {
1106 out_device = adev->primary_output->devices;
1107 } else {
1108 list_for_each(node, &adev->usecase_list) {
1109 uinfo = node_to_item(node, struct audio_usecase, list);
1110 if (uinfo->type != PCM_CAPTURE) {
1111 out_device = uinfo->stream.out->devices;
1112 break;
1113 }
1114 }
1115 }
1116 platform_set_echo_reference(adev, true, out_device);
1117 in->ec_opened = true;
1118 }
1119 }
1120 } else if (usecase->type == TRANSCODE_LOOPBACK_TX) {
1121 snd_device = usecase->in_snd_device;
1122 } else {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001123 snd_device = usecase->out_snd_device;
Carter Hsu2e429db2019-05-14 18:50:52 +08001124 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001125
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001126#ifdef DS1_DOLBY_DAP_ENABLED
1127 audio_extn_dolby_set_dmid(adev);
1128 audio_extn_dolby_set_endpoint(adev);
1129#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001130 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001131 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301132 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001133 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001134 if (audio_extn_is_maxx_audio_enabled())
1135 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301136 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301137 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1138 out = usecase->stream.out;
1139 if (out && out->compr)
1140 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1141 }
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301142 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301143
Andy Hung756ecc12018-10-19 17:47:12 -07001144 // we shouldn't truncate mixer_path
1145 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1146 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1147 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001148 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001149 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301150 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1151 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1152 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1153 if (parms) {
1154 audio_extn_fm_set_parameters(adev, parms);
1155 str_parms_destroy(parms);
1156 }
1157 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001158 ALOGV("%s: exit", __func__);
1159 return 0;
1160}
1161
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001162int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001163 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001164{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001165 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001166 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001167
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301168 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001169 return -EINVAL;
1170
1171 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301172 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001173 snd_device = usecase->in_snd_device;
1174 else
1175 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001176 // we shouldn't truncate mixer_path
1177 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1178 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1179 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001180 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001181 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001182 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Carter Hsu2e429db2019-05-14 18:50:52 +08001183 if (usecase->type == PCM_CAPTURE) {
1184 struct stream_in *in = usecase->stream.in;
1185 if (in && in->ec_opened) {
1186 platform_set_echo_reference(in->dev, false, AUDIO_DEVICE_NONE);
1187 in->ec_opened = false;
1188 }
1189 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001190 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301191 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301192 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001193 if ((usecase->type == PCM_PLAYBACK) &&
1194 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301195 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001196 ALOGV("%s: exit", __func__);
1197 return 0;
1198}
1199
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001200int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001201 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001202{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301203 int i, num_devices = 0;
1204 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001205 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1206
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001207 if (snd_device < SND_DEVICE_MIN ||
1208 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001209 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001210 return -EINVAL;
1211 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001212
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001213 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001214 ALOGE("%s: Invalid sound device returned", __func__);
1215 return -EINVAL;
1216 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001217
1218 adev->snd_dev_ref_cnt[snd_device]++;
1219
1220 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1221 (platform_split_snd_device(adev->platform,
1222 snd_device,
1223 &num_devices,
1224 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001225 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001226 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001227 return 0;
1228 }
1229
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001230 if (audio_extn_spkr_prot_is_enabled())
1231 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001232
Aalique Grahame22e49102018-12-18 14:23:57 -08001233 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1234
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001235 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1236 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001237 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1238 goto err;
1239 }
1240 audio_extn_dev_arbi_acquire(snd_device);
1241 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001242 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001243 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001244 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001245 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001246 } else if (platform_split_snd_device(adev->platform,
1247 snd_device,
1248 &num_devices,
1249 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301250 for (i = 0; i < num_devices; i++) {
1251 enable_snd_device(adev, new_snd_devices[i]);
1252 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001253 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001254 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001255 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301256
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301257
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001258 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1259 (audio_extn_a2dp_start_playback() < 0)) {
1260 ALOGE(" fail to configure A2dp Source control path ");
1261 goto err;
1262 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001263
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001264 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1265 (audio_extn_a2dp_start_capture() < 0)) {
1266 ALOGE(" fail to configure A2dp Sink control path ");
1267 goto err;
1268 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301269
Zhou Song12c29502019-03-16 10:37:18 +08001270 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1271 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1272 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1273 (audio_extn_sco_start_configuration() < 0)) {
1274 ALOGE(" fail to configure sco control path ");
1275 goto err;
1276 }
1277
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001278 /* due to the possibility of calibration overwrite between listen
1279 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001280 audio_extn_sound_trigger_update_device_status(snd_device,
1281 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301282 audio_extn_listen_update_device_status(snd_device,
1283 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001284 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001285 audio_extn_sound_trigger_update_device_status(snd_device,
1286 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301287 audio_extn_listen_update_device_status(snd_device,
1288 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001289 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001290 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001291 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001292 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301293
1294 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1295 !adev->native_playback_enabled &&
1296 audio_is_true_native_stream_active(adev)) {
1297 ALOGD("%s: %d: napb: enabling native mode in hardware",
1298 __func__, __LINE__);
1299 audio_route_apply_and_update_path(adev->audio_route,
1300 "true-native-mode");
1301 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301302 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301303 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1304 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001305 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001306 ALOGD("%s: init ec ref loopback", __func__);
1307 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1308 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001309 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001310 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001311err:
1312 adev->snd_dev_ref_cnt[snd_device]--;
1313 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001314}
1315
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001316int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001317 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301319 int i, num_devices = 0;
1320 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001321 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1322
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001323 if (snd_device < SND_DEVICE_MIN ||
1324 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001325 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001326 return -EINVAL;
1327 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001328
1329 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1330 ALOGE("%s: Invalid sound device returned", __func__);
1331 return -EINVAL;
1332 }
1333
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001334 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1335 ALOGE("%s: device ref cnt is already 0", __func__);
1336 return -EINVAL;
1337 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001338
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001339 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001340
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001341
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001342 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001343 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301344
Aalique Grahame22e49102018-12-18 14:23:57 -08001345 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1346
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001347 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1348 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001349 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001350
1351 // when speaker device is disabled, reset swap.
1352 // will be renabled on usecase start
1353 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001354 } else if (platform_split_snd_device(adev->platform,
1355 snd_device,
1356 &num_devices,
1357 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301358 for (i = 0; i < num_devices; i++) {
1359 disable_snd_device(adev, new_snd_devices[i]);
1360 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001361 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001362 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001363 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001364 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001365
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001366 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301367 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001368 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001369 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001370 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001371 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301372 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001373 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301374 adev->native_playback_enabled) {
1375 ALOGD("%s: %d: napb: disabling native mode in hardware",
1376 __func__, __LINE__);
1377 audio_route_reset_and_update_path(adev->audio_route,
1378 "true-native-mode");
1379 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001380 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301381 adev->asrc_mode_enabled) {
1382 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301383 disable_asrc_mode(adev);
1384 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001385 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301386 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001387 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001388 ALOGD("%s: deinit ec ref loopback", __func__);
1389 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1390 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001391
1392 audio_extn_utils_release_snd_device(snd_device);
1393 } else {
1394 if (platform_split_snd_device(adev->platform,
1395 snd_device,
1396 &num_devices,
1397 new_snd_devices) == 0) {
1398 for (i = 0; i < num_devices; i++) {
1399 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1400 }
1401 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001402 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001403
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001404 return 0;
1405}
1406
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001407/*
1408 legend:
1409 uc - existing usecase
1410 new_uc - new usecase
1411 d1, d11, d2 - SND_DEVICE enums
1412 a1, a2 - corresponding ANDROID device enums
1413 B1, B2 - backend strings
1414
1415case 1
1416 uc->dev d1 (a1) B1
1417 new_uc->dev d1 (a1), d2 (a2) B1, B2
1418
1419 resolution: disable and enable uc->dev on d1
1420
1421case 2
1422 uc->dev d1 (a1) B1
1423 new_uc->dev d11 (a1) B1
1424
1425 resolution: need to switch uc since d1 and d11 are related
1426 (e.g. speaker and voice-speaker)
1427 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1428
1429case 3
1430 uc->dev d1 (a1) B1
1431 new_uc->dev d2 (a2) B2
1432
1433 resolution: no need to switch uc
1434
1435case 4
1436 uc->dev d1 (a1) B1
1437 new_uc->dev d2 (a2) B1
1438
1439 resolution: disable enable uc-dev on d2 since backends match
1440 we cannot enable two streams on two different devices if they
1441 share the same backend. e.g. if offload is on speaker device using
1442 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1443 using the same backend, offload must also be switched to voice-handset.
1444
1445case 5
1446 uc->dev d1 (a1) B1
1447 new_uc->dev d1 (a1), d2 (a2) B1
1448
1449 resolution: disable enable uc-dev on d2 since backends match
1450 we cannot enable two streams on two different devices if they
1451 share the same backend.
1452
1453case 6
1454 uc->dev d1 (a1) B1
1455 new_uc->dev d2 (a1) B2
1456
1457 resolution: no need to switch
1458
1459case 7
1460 uc->dev d1 (a1), d2 (a2) B1, B2
1461 new_uc->dev d1 (a1) B1
1462
1463 resolution: no need to switch
1464
Zhou Song4ba65882018-07-09 14:48:07 +08001465case 8
1466 uc->dev d1 (a1) B1
1467 new_uc->dev d11 (a1), d2 (a2) B1, B2
1468 resolution: compared to case 1, for this case, d1 and d11 are related
1469 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001470*/
1471static snd_device_t derive_playback_snd_device(void * platform,
1472 struct audio_usecase *uc,
1473 struct audio_usecase *new_uc,
1474 snd_device_t new_snd_device)
1475{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301476 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001477
1478 snd_device_t d1 = uc->out_snd_device;
1479 snd_device_t d2 = new_snd_device;
1480
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301481 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301482 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301483 a1 = uc->stream.inout->out_config.devices;
1484 a2 = new_uc->stream.inout->out_config.devices;
1485 break;
1486 default :
1487 a1 = uc->stream.out->devices;
1488 a2 = new_uc->stream.out->devices;
1489 break;
1490 }
1491
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001492 // Treat as a special case when a1 and a2 are not disjoint
1493 if ((a1 != a2) && (a1 & a2)) {
1494 snd_device_t d3[2];
1495 int num_devices = 0;
1496 int ret = platform_split_snd_device(platform,
1497 popcount(a1) > 1 ? d1 : d2,
1498 &num_devices,
1499 d3);
1500 if (ret < 0) {
1501 if (ret != -ENOSYS) {
1502 ALOGW("%s failed to split snd_device %d",
1503 __func__,
1504 popcount(a1) > 1 ? d1 : d2);
1505 }
1506 goto end;
1507 }
1508
1509 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1510 // But if it does happen, we need to give priority to d2 if
1511 // the combo devices active on the existing usecase share a backend.
1512 // This is because we cannot have a usecase active on a combo device
1513 // and a new usecase requests one device in this combo pair.
1514 if (platform_check_backends_match(d3[0], d3[1])) {
1515 return d2; // case 5
1516 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001517 // check if d1 is related to any of d3's
1518 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001519 return d1; // case 1
1520 else
1521 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001522 }
1523 } else {
1524 if (platform_check_backends_match(d1, d2)) {
1525 return d2; // case 2, 4
1526 } else {
1527 return d1; // case 6, 3
1528 }
1529 }
1530
1531end:
1532 return d2; // return whatever was calculated before.
1533}
1534
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301536 struct audio_usecase *uc_info,
1537 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538{
1539 struct listnode *node;
1540 struct audio_usecase *usecase;
1541 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301542 snd_device_t uc_derive_snd_device;
1543 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001544 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1545 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001546 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301547 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001548 /*
1549 * This function is to make sure that all the usecases that are active on
1550 * the hardware codec backend are always routed to any one device that is
1551 * handled by the hardware codec.
1552 * For example, if low-latency and deep-buffer usecases are currently active
1553 * on speaker and out_set_parameters(headset) is received on low-latency
1554 * output, then we have to make sure deep-buffer is also switched to headset,
1555 * because of the limitation that both the devices cannot be enabled
1556 * at the same time as they share the same backend.
1557 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001558 /*
1559 * This call is to check if we need to force routing for a particular stream
1560 * If there is a backend configuration change for the device when a
1561 * new stream starts, then ADM needs to be closed and re-opened with the new
1562 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001563 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001564 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001565 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1566 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301567 /* For a2dp device reconfigure all active sessions
1568 * with new AFE encoder format based on a2dp state
1569 */
1570 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1571 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1572 audio_extn_a2dp_is_force_device_switch()) {
1573 force_routing = true;
1574 force_restart_session = true;
1575 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301576 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1577
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001578 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001579 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001580 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001581 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1582 switch_device[i] = false;
1583
1584 list_for_each(node, &adev->usecase_list) {
1585 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001586
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301587 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1588 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301589 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301590 platform_get_snd_device_name(usecase->out_snd_device),
1591 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301592 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1593 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1594 usecase, uc_info, snd_device);
1595 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1596 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1597 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1598 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001599 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301600 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1601 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1602 ((force_restart_session) ||
1603 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301604 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1605 __func__, use_case_table[usecase->id],
1606 platform_get_snd_device_name(usecase->out_snd_device));
1607 disable_audio_route(adev, usecase);
1608 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301609 /* Enable existing usecase on derived playback device */
1610 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301611 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301612 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001613 }
1614 }
1615
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301616 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1617 num_uc_to_switch);
1618
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001619 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001620 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001621
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301622 /* Make sure the previous devices to be disabled first and then enable the
1623 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001624 list_for_each(node, &adev->usecase_list) {
1625 usecase = node_to_item(node, struct audio_usecase, list);
1626 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001627 /* Check if output sound device to be switched can be split and if any
1628 of the split devices match with derived sound device */
1629 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1630 &num_devices, split_snd_devices) == 0) {
1631 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1632 for (i = 0; i < num_devices; i++) {
1633 /* Disable devices that do not match with derived sound device */
1634 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1635 disable_snd_device(adev, split_snd_devices[i]);
1636 }
1637 } else {
1638 disable_snd_device(adev, usecase->out_snd_device);
1639 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001640 }
1641 }
1642
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001643 list_for_each(node, &adev->usecase_list) {
1644 usecase = node_to_item(node, struct audio_usecase, list);
1645 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001646 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1647 &num_devices, split_snd_devices) == 0) {
1648 /* Enable derived sound device only if it does not match with
1649 one of the split sound devices. This is because the matching
1650 sound device was not disabled */
1651 bool should_enable = true;
1652 for (i = 0; i < num_devices; i++) {
1653 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1654 should_enable = false;
1655 break;
1656 }
1657 }
1658 if (should_enable)
1659 enable_snd_device(adev, derive_snd_device[usecase->id]);
1660 } else {
1661 enable_snd_device(adev, derive_snd_device[usecase->id]);
1662 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001663 }
1664 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001665
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001666 /* Re-route all the usecases on the shared backend other than the
1667 specified usecase to new snd devices */
1668 list_for_each(node, &adev->usecase_list) {
1669 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301670 /* Update the out_snd_device only before enabling the audio route */
1671 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301672 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301673 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301674 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301675 use_case_table[usecase->id],
1676 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001677 /* Update voc calibration before enabling VoIP route */
1678 if (usecase->type == VOIP_CALL)
1679 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001680 usecase->out_snd_device,
1681 platform_get_input_snd_device(
1682 adev->platform, NULL,
1683 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301684 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301685 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001686 out_set_voip_volume(&usecase->stream.out->stream,
1687 usecase->stream.out->volume_l,
1688 usecase->stream.out->volume_r);
1689 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301690 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001691 }
1692 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001693 }
1694}
1695
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301696static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001697 struct audio_usecase *uc_info,
1698 snd_device_t snd_device)
1699{
1700 struct listnode *node;
1701 struct audio_usecase *usecase;
1702 bool switch_device[AUDIO_USECASE_MAX];
1703 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301704 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001705 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001706
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301707 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1708 snd_device);
1709 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301710
1711 /*
1712 * Make sure out devices is checked against out codec backend device and
1713 * also in devices against in codec backend. Checking out device against in
1714 * codec backend or vice versa causes issues.
1715 */
1716 if (uc_info->type == PCM_CAPTURE)
1717 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001718 /*
1719 * This function is to make sure that all the active capture usecases
1720 * are always routed to the same input sound device.
1721 * For example, if audio-record and voice-call usecases are currently
1722 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1723 * is received for voice call then we have to make sure that audio-record
1724 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1725 * because of the limitation that two devices cannot be enabled
1726 * at the same time if they share the same backend.
1727 */
1728 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1729 switch_device[i] = false;
1730
1731 list_for_each(node, &adev->usecase_list) {
1732 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301733 /*
1734 * TODO: Enhance below condition to handle BT sco/USB multi recording
1735 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001736 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001737 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301738 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301739 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301740 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301741 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001742 ((uc_info->type == VOICE_CALL &&
1743 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1744 platform_check_backends_match(snd_device,\
1745 usecase->in_snd_device)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001746 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001747 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1748 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001749 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001750 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001751 switch_device[usecase->id] = true;
1752 num_uc_to_switch++;
1753 }
1754 }
1755
1756 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001757 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001758
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301759 /* Make sure the previous devices to be disabled first and then enable the
1760 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001761 list_for_each(node, &adev->usecase_list) {
1762 usecase = node_to_item(node, struct audio_usecase, list);
1763 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001764 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001765 }
1766 }
1767
1768 list_for_each(node, &adev->usecase_list) {
1769 usecase = node_to_item(node, struct audio_usecase, list);
1770 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001771 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001772 }
1773 }
1774
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001775 /* Re-route all the usecases on the shared backend other than the
1776 specified usecase to new snd devices */
1777 list_for_each(node, &adev->usecase_list) {
1778 usecase = node_to_item(node, struct audio_usecase, list);
1779 /* Update the in_snd_device only before enabling the audio route */
1780 if (switch_device[usecase->id] ) {
1781 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001782 if (usecase->type != VOICE_CALL) {
1783 /* Update voc calibration before enabling VoIP route */
1784 if (usecase->type == VOIP_CALL)
1785 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001786 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001787 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301788 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001789 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001790 }
1791 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001792 }
1793}
1794
Mingming Yin3a941d42016-02-17 18:08:05 -08001795static void reset_hdmi_sink_caps(struct stream_out *out) {
1796 int i = 0;
1797
1798 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1799 out->supported_channel_masks[i] = 0;
1800 }
1801 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1802 out->supported_formats[i] = 0;
1803 }
1804 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1805 out->supported_sample_rates[i] = 0;
1806 }
1807}
1808
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001809/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001810static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001811{
Mingming Yin3a941d42016-02-17 18:08:05 -08001812 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001813 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001814
Mingming Yin3a941d42016-02-17 18:08:05 -08001815 reset_hdmi_sink_caps(out);
1816
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001817 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001818 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001819 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001820 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001821 }
1822
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001823 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001824 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001825 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001826 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001827 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1828 case 6:
1829 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1830 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1831 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1832 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1833 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1834 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001835 break;
1836 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001837 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001838 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001839 break;
1840 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001841
1842 // check channel format caps
1843 i = 0;
1844 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1845 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1846 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1847 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1848 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1849 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1850 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1851 }
1852
Ben Romberger1aaaf862017-04-06 17:49:46 -07001853 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1854 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1855 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1856 }
1857
Mingming Yin3a941d42016-02-17 18:08:05 -08001858 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1859 ALOGV(":%s HDMI supports DTS format", __func__);
1860 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1861 }
1862
1863 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1864 ALOGV(":%s HDMI supports DTS HD format", __func__);
1865 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1866 }
1867
Naresh Tanniru928f0862017-04-07 16:44:23 -07001868 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1869 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1870 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1871 }
1872
Mingming Yin3a941d42016-02-17 18:08:05 -08001873
1874 // check sample rate caps
1875 i = 0;
1876 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1877 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1878 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1879 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1880 }
1881 }
1882
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001883 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001884}
1885
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001886static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1887 uint32_t *supported_sample_rates __unused,
1888 uint32_t max_rates __unused)
1889{
1890 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1891 supported_sample_rates,
1892 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301893 ssize_t i = 0;
1894
1895 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001896 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1897 supported_sample_rates[i]);
1898 }
1899 return count;
1900}
1901
1902static inline int read_usb_sup_channel_masks(bool is_playback,
1903 audio_channel_mask_t *supported_channel_masks,
1904 uint32_t max_masks)
1905{
1906 int channels = audio_extn_usb_get_max_channels(is_playback);
1907 int channel_count;
1908 uint32_t num_masks = 0;
1909 if (channels > MAX_HIFI_CHANNEL_COUNT)
1910 channels = MAX_HIFI_CHANNEL_COUNT;
1911
1912 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001913 // start from 2 channels as framework currently doesn't support mono.
1914 if (channels >= FCC_2) {
1915 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1916 }
1917 for (channel_count = FCC_2;
1918 channel_count <= channels && num_masks < max_masks;
1919 ++channel_count) {
1920 supported_channel_masks[num_masks++] =
1921 audio_channel_mask_for_index_assignment_from_count(channel_count);
1922 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001923 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001924 // For capture we report all supported channel masks from 1 channel up.
1925 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001926 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1927 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001928 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1929 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1930 if (channel_count <= FCC_2) {
1931 mask = audio_channel_in_mask_from_count(channel_count);
1932 supported_channel_masks[num_masks++] = mask;
1933 }
1934 const audio_channel_mask_t index_mask =
1935 audio_channel_mask_for_index_assignment_from_count(channel_count);
1936 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1937 supported_channel_masks[num_masks++] = index_mask;
1938 }
1939 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001940 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301941
vincenttewf51c94e2019-05-07 10:28:53 +08001942 for (size_t i = 0; i < num_masks; ++i) {
1943 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1944 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301945 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001946 return num_masks;
1947}
1948
1949static inline int read_usb_sup_formats(bool is_playback __unused,
1950 audio_format_t *supported_formats,
1951 uint32_t max_formats __unused)
1952{
1953 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1954 switch (bitwidth) {
1955 case 24:
1956 // XXX : usb.c returns 24 for s24 and s24_le?
1957 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1958 break;
1959 case 32:
1960 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1961 break;
1962 case 16:
1963 default :
1964 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1965 break;
1966 }
1967 ALOGV("%s: %s supported format %d", __func__,
1968 is_playback ? "P" : "C", bitwidth);
1969 return 1;
1970}
1971
1972static inline int read_usb_sup_params_and_compare(bool is_playback,
1973 audio_format_t *format,
1974 audio_format_t *supported_formats,
1975 uint32_t max_formats,
1976 audio_channel_mask_t *mask,
1977 audio_channel_mask_t *supported_channel_masks,
1978 uint32_t max_masks,
1979 uint32_t *rate,
1980 uint32_t *supported_sample_rates,
1981 uint32_t max_rates) {
1982 int ret = 0;
1983 int num_formats;
1984 int num_masks;
1985 int num_rates;
1986 int i;
1987
1988 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1989 max_formats);
1990 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1991 max_masks);
1992
1993 num_rates = read_usb_sup_sample_rates(is_playback,
1994 supported_sample_rates, max_rates);
1995
1996#define LUT(table, len, what, dflt) \
1997 for (i=0; i<len && (table[i] != what); i++); \
1998 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1999
2000 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
2001 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
2002 LUT(supported_sample_rates, num_rates, *rate, 0);
2003
2004#undef LUT
2005 return ret < 0 ? -EINVAL : 0; // HACK TBD
2006}
2007
Alexy Josephb1379942016-01-29 15:49:38 -08002008audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002009 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002010{
2011 struct audio_usecase *usecase;
2012 struct listnode *node;
2013
2014 list_for_each(node, &adev->usecase_list) {
2015 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002016 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002017 ALOGV("%s: usecase id %d", __func__, usecase->id);
2018 return usecase->id;
2019 }
2020 }
2021 return USECASE_INVALID;
2022}
2023
Alexy Josephb1379942016-01-29 15:49:38 -08002024struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002025 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002026{
2027 struct audio_usecase *usecase;
2028 struct listnode *node;
2029
2030 list_for_each(node, &adev->usecase_list) {
2031 usecase = node_to_item(node, struct audio_usecase, list);
2032 if (usecase->id == uc_id)
2033 return usecase;
2034 }
2035 return NULL;
2036}
2037
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302038/*
2039 * is a true native playback active
2040 */
2041bool audio_is_true_native_stream_active(struct audio_device *adev)
2042{
2043 bool active = false;
2044 int i = 0;
2045 struct listnode *node;
2046
2047 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2048 ALOGV("%s:napb: not in true mode or non hdphones device",
2049 __func__);
2050 active = false;
2051 goto exit;
2052 }
2053
2054 list_for_each(node, &adev->usecase_list) {
2055 struct audio_usecase *uc;
2056 uc = node_to_item(node, struct audio_usecase, list);
2057 struct stream_out *curr_out =
2058 (struct stream_out*) uc->stream.out;
2059
2060 if (curr_out && PCM_PLAYBACK == uc->type) {
2061 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2062 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2063 uc->id, curr_out->sample_rate,
2064 curr_out->bit_width,
2065 platform_get_snd_device_name(uc->out_snd_device));
2066
2067 if (is_offload_usecase(uc->id) &&
2068 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2069 active = true;
2070 ALOGD("%s:napb:native stream detected", __func__);
2071 }
2072 }
2073 }
2074exit:
2075 return active;
2076}
2077
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002078uint32_t adev_get_dsp_bit_width_enforce_mode()
2079{
2080 if (adev == NULL) {
2081 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2082 return 0;
2083 }
2084 return adev->dsp_bit_width_enforce_mode;
2085}
2086
2087static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2088{
2089 char value[PROPERTY_VALUE_MAX];
2090 int trial;
2091 uint32_t dsp_bit_width_enforce_mode = 0;
2092
2093 if (!mixer) {
2094 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2095 __func__);
2096 return 0;
2097 }
2098
2099 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2100 value, NULL) > 0) {
2101 trial = atoi(value);
2102 switch (trial) {
2103 case 16:
2104 dsp_bit_width_enforce_mode = 16;
2105 break;
2106 case 24:
2107 dsp_bit_width_enforce_mode = 24;
2108 break;
2109 case 32:
2110 dsp_bit_width_enforce_mode = 32;
2111 break;
2112 default:
2113 dsp_bit_width_enforce_mode = 0;
2114 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2115 break;
2116 }
2117 }
2118
2119 return dsp_bit_width_enforce_mode;
2120}
2121
2122static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2123 uint32_t enforce_mode,
2124 bool enable)
2125{
2126 struct mixer_ctl *ctl = NULL;
2127 const char *mixer_ctl_name = "ASM Bit Width";
2128 uint32_t asm_bit_width_mode = 0;
2129
2130 if (enforce_mode == 0) {
2131 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2132 return;
2133 }
2134
2135 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2136 if (!ctl) {
2137 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2138 __func__, mixer_ctl_name);
2139 return;
2140 }
2141
2142 if (enable)
2143 asm_bit_width_mode = enforce_mode;
2144 else
2145 asm_bit_width_mode = 0;
2146
2147 ALOGV("%s DSP bit width feature status is %d width=%d",
2148 __func__, enable, asm_bit_width_mode);
2149 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2150 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2151 asm_bit_width_mode);
2152
2153 return;
2154}
2155
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302156/*
2157 * if native DSD playback active
2158 */
2159bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2160{
2161 bool active = false;
2162 struct listnode *node = NULL;
2163 struct audio_usecase *uc = NULL;
2164 struct stream_out *curr_out = NULL;
2165
2166 list_for_each(node, &adev->usecase_list) {
2167 uc = node_to_item(node, struct audio_usecase, list);
2168 curr_out = (struct stream_out*) uc->stream.out;
2169
2170 if (curr_out && PCM_PLAYBACK == uc->type &&
2171 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2172 active = true;
2173 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302174 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302175 }
2176 }
2177 return active;
2178}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302179
2180static bool force_device_switch(struct audio_usecase *usecase)
2181{
2182 bool ret = false;
2183 bool is_it_true_mode = false;
2184
Zhou Song30f2c3e2018-02-08 14:02:15 +08002185 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302186 usecase->type == TRANSCODE_LOOPBACK_RX ||
2187 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002188 return false;
2189 }
2190
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002191 if(usecase->stream.out == NULL) {
2192 ALOGE("%s: stream.out is NULL", __func__);
2193 return false;
2194 }
2195
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302196 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002197 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2198 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2199 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302200 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2201 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2202 (!is_it_true_mode && adev->native_playback_enabled)){
2203 ret = true;
2204 ALOGD("napb: time to toggle native mode");
2205 }
2206 }
2207
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302208 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302209 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2210 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002211 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302212 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302213 ALOGD("Force a2dp device switch to update new encoder config");
2214 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002215 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302216
Florian Pfister1a84f312018-07-19 14:38:18 +02002217 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302218 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2219 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002220 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302221 return ret;
2222}
2223
Aalique Grahame22e49102018-12-18 14:23:57 -08002224static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2225{
2226 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2227}
2228
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302229bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2230{
2231 bool ret=false;
2232 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2233 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2234 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2235 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2236 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2237 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2238 ret = true;
2239
2240 return ret;
2241}
2242
2243bool is_a2dp_device(snd_device_t out_snd_device)
2244{
2245 bool ret=false;
2246 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2247 ret = true;
2248
2249 return ret;
2250}
2251
2252bool is_bt_soc_on(struct audio_device *adev)
2253{
2254 struct mixer_ctl *ctl;
2255 char *mixer_ctl_name = "BT SOC status";
2256 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2257 bool bt_soc_status = true;
2258 if (!ctl) {
2259 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2260 __func__, mixer_ctl_name);
2261 /*This is to ensure we dont break targets which dont have the kernel change*/
2262 return true;
2263 }
2264 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2265 ALOGD("BT SOC status: %d",bt_soc_status);
2266 return bt_soc_status;
2267}
2268
2269int out_standby_l(struct audio_stream *stream);
2270
Eric Laurent637e2d42018-11-15 12:24:31 -08002271struct stream_in *adev_get_active_input(const struct audio_device *adev)
2272{
2273 struct listnode *node;
2274 struct stream_in *last_active_in = NULL;
2275
2276 /* Get last added active input.
2277 * TODO: We may use a priority mechanism to pick highest priority active source */
2278 list_for_each(node, &adev->usecase_list)
2279 {
2280 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2281 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2282 last_active_in = usecase->stream.in;
2283 }
2284
2285 return last_active_in;
2286}
2287
2288struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2289{
2290 struct listnode *node;
2291
2292 /* First check active inputs with voice communication source and then
2293 * any input if audio mode is in communication */
2294 list_for_each(node, &adev->usecase_list)
2295 {
2296 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2297 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2298 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2299 return usecase->stream.in;
2300 }
2301 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2302 return adev_get_active_input(adev);
2303
2304 return NULL;
2305}
2306
Carter Hsu2e429db2019-05-14 18:50:52 +08002307/*
2308 * Aligned with policy.h
2309 */
2310static inline int source_priority(int inputSource)
2311{
2312 switch (inputSource) {
2313 case AUDIO_SOURCE_VOICE_COMMUNICATION:
2314 return 9;
2315 case AUDIO_SOURCE_CAMCORDER:
2316 return 8;
2317 case AUDIO_SOURCE_VOICE_PERFORMANCE:
2318 return 7;
2319 case AUDIO_SOURCE_UNPROCESSED:
2320 return 6;
2321 case AUDIO_SOURCE_MIC:
2322 return 5;
2323 case AUDIO_SOURCE_ECHO_REFERENCE:
2324 return 4;
2325 case AUDIO_SOURCE_FM_TUNER:
2326 return 3;
2327 case AUDIO_SOURCE_VOICE_RECOGNITION:
2328 return 2;
2329 case AUDIO_SOURCE_HOTWORD:
2330 return 1;
2331 default:
2332 break;
2333 }
2334 return 0;
2335}
2336
2337static struct stream_in *get_priority_input(struct audio_device *adev)
2338{
2339 struct listnode *node;
2340 struct audio_usecase *usecase;
2341 int last_priority = 0, priority;
2342 struct stream_in *priority_in = NULL;
2343 struct stream_in *in;
2344
2345 list_for_each(node, &adev->usecase_list) {
2346 usecase = node_to_item(node, struct audio_usecase, list);
2347 if (usecase->type == PCM_CAPTURE) {
2348 in = usecase->stream.in;
2349 if (!in)
2350 continue;
2351 priority = source_priority(in->source);
2352
2353 if (priority > last_priority) {
2354 last_priority = priority;
2355 priority_in = in;
2356 }
2357 }
2358 }
2359 return priority_in;
2360}
2361
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002362int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002363{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002364 snd_device_t out_snd_device = SND_DEVICE_NONE;
2365 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002366 struct audio_usecase *usecase = NULL;
2367 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002368 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002369 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302370 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002371 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002372 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002373
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302374 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2375
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002376 usecase = get_usecase_from_list(adev, uc_id);
2377 if (usecase == NULL) {
2378 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2379 return -EINVAL;
2380 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002381
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002382 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002383 (usecase->type == VOIP_CALL) ||
2384 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302385 if(usecase->stream.out == NULL) {
2386 ALOGE("%s: stream.out is NULL", __func__);
2387 return -EINVAL;
2388 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002389 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002390 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002391 in_snd_device = platform_get_input_snd_device(adev->platform,
2392 NULL,
2393 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002394 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302395 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302396 if (usecase->stream.inout == NULL) {
2397 ALOGE("%s: stream.inout is NULL", __func__);
2398 return -EINVAL;
2399 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302400 stream_out.devices = usecase->stream.inout->out_config.devices;
2401 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2402 stream_out.format = usecase->stream.inout->out_config.format;
2403 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2404 out_snd_device = platform_get_output_snd_device(adev->platform,
2405 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302406 usecase->devices = out_snd_device;
2407 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2408 if (usecase->stream.inout == NULL) {
2409 ALOGE("%s: stream.inout is NULL", __func__);
2410 return -EINVAL;
2411 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002412 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302413 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002414 } else {
2415 /*
2416 * If the voice call is active, use the sound devices of voice call usecase
2417 * so that it would not result any device switch. All the usecases will
2418 * be switched to new device when select_devices() is called for voice call
2419 * usecase. This is to avoid switching devices for voice call when
2420 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002421 * choose voice call device only if the use case device is
2422 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002423 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002424 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002425 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002426 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002427 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2428 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302429 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2430 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002431 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2432 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002433 in_snd_device = vc_usecase->in_snd_device;
2434 out_snd_device = vc_usecase->out_snd_device;
2435 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002436 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002437 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002438 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002439 if ((voip_usecase != NULL) &&
2440 (usecase->type == PCM_PLAYBACK) &&
2441 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002442 out_snd_device_backend_match = platform_check_backends_match(
2443 voip_usecase->out_snd_device,
2444 platform_get_output_snd_device(
2445 adev->platform,
2446 usecase->stream.out));
2447 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002448 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002449 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2450 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002451 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002452 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002453 in_snd_device = voip_usecase->in_snd_device;
2454 out_snd_device = voip_usecase->out_snd_device;
2455 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002456 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002457 hfp_ucid = audio_extn_hfp_get_usecase();
2458 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002459 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002460 in_snd_device = hfp_usecase->in_snd_device;
2461 out_snd_device = hfp_usecase->out_snd_device;
2462 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002463 }
2464 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302465 if (usecase->stream.out == NULL) {
2466 ALOGE("%s: stream.out is NULL", __func__);
2467 return -EINVAL;
2468 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002469 usecase->devices = usecase->stream.out->devices;
2470 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002471 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002472 struct stream_out *voip_out = adev->primary_output;
2473 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002474 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002475 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002476 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002477
Eric Laurent637e2d42018-11-15 12:24:31 -08002478 if (voip_usecase)
2479 voip_out = voip_usecase->stream.out;
2480
2481 if (usecase->stream.out == voip_out && voip_in != NULL)
2482 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002483 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002484 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302485 if (usecase->stream.in == NULL) {
2486 ALOGE("%s: stream.in is NULL", __func__);
2487 return -EINVAL;
2488 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002489 usecase->devices = usecase->stream.in->device;
2490 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002491 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002492 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002493 struct stream_in *voip_in = get_voice_communication_input(adev);
Carter Hsu2e429db2019-05-14 18:50:52 +08002494 struct stream_in *priority_in = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -08002495
2496 if (voip_in != NULL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002497 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2498 USECASE_AUDIO_PLAYBACK_VOIP);
2499
Carter Hsu2e429db2019-05-14 18:50:52 +08002500 usecase->stream.in->enable_ec_port = false;
2501
Eric Laurent637e2d42018-11-15 12:24:31 -08002502 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2503 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2504 } else if (voip_usecase) {
2505 out_device = voip_usecase->stream.out->devices;
2506 } else if (adev->primary_output &&
2507 !adev->primary_output->standby) {
2508 out_device = adev->primary_output->devices;
2509 } else {
2510 /* forcing speaker o/p device to get matching i/p pair
2511 in case o/p is not routed from same primary HAL */
2512 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2513 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002514 priority_in = voip_in;
2515 } else {
2516 /* get the input with the highest priority source*/
2517 priority_in = get_priority_input(adev);
2518
2519 if (!priority_in)
2520 priority_in = usecase->stream.in;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002521 }
Carter Hsu2e429db2019-05-14 18:50:52 +08002522
Eric Laurent637e2d42018-11-15 12:24:31 -08002523 in_snd_device = platform_get_input_snd_device(adev->platform,
Carter Hsu2e429db2019-05-14 18:50:52 +08002524 priority_in,
Eric Laurent637e2d42018-11-15 12:24:31 -08002525 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002526 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002527 }
2528 }
2529
2530 if (out_snd_device == usecase->out_snd_device &&
2531 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302532
2533 if (!force_device_switch(usecase))
2534 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002535 }
2536
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302537 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002538 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302539 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2540 return 0;
2541 }
2542
Aalique Grahame22e49102018-12-18 14:23:57 -08002543 if (out_snd_device != SND_DEVICE_NONE &&
2544 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2545 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2546 __func__,
2547 use_case_table[uc_id],
2548 adev->last_logged_snd_device[uc_id][0],
2549 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2550 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2551 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2552 -1,
2553 out_snd_device,
2554 platform_get_snd_device_name(out_snd_device),
2555 platform_get_snd_device_acdb_id(out_snd_device));
2556 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2557 }
2558 if (in_snd_device != SND_DEVICE_NONE &&
2559 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2560 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2561 __func__,
2562 use_case_table[uc_id],
2563 adev->last_logged_snd_device[uc_id][1],
2564 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2565 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2566 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2567 -1,
2568 in_snd_device,
2569 platform_get_snd_device_name(in_snd_device),
2570 platform_get_snd_device_acdb_id(in_snd_device));
2571 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2572 }
2573
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002574
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002575 /*
2576 * Limitation: While in call, to do a device switch we need to disable
2577 * and enable both RX and TX devices though one of them is same as current
2578 * device.
2579 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002580 if ((usecase->type == VOICE_CALL) &&
2581 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2582 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002583 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002584 }
2585
2586 if (((usecase->type == VOICE_CALL) ||
2587 (usecase->type == VOIP_CALL)) &&
2588 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2589 /* Disable sidetone only if voice/voip call already exists */
2590 if (voice_is_call_state_active(adev) ||
2591 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002592 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002593
2594 /* Disable aanc only if voice call exists */
2595 if (voice_is_call_state_active(adev))
2596 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002597 }
2598
Aalique Grahame22e49102018-12-18 14:23:57 -08002599 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2600 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002601 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302602 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002603 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2604 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2605 else
2606 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302607 }
2608
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002609 /* Disable current sound devices */
2610 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002611 disable_audio_route(adev, usecase);
2612 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002613 }
2614
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002615 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002616 disable_audio_route(adev, usecase);
2617 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002618 }
2619
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002620 /* Applicable only on the targets that has external modem.
2621 * New device information should be sent to modem before enabling
2622 * the devices to reduce in-call device switch time.
2623 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002624 if ((usecase->type == VOICE_CALL) &&
2625 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2626 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002627 status = platform_switch_voice_call_enable_device_config(adev->platform,
2628 out_snd_device,
2629 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002630 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002631
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002632 /* Enable new sound devices */
2633 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002634 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302635 if (platform_check_codec_asrc_support(adev->platform))
2636 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002637 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638 }
2639
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002640 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302641 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002642 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002643 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002644
Avinash Vaish71a8b972014-07-24 15:36:33 +05302645 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002646 status = platform_switch_voice_call_device_post(adev->platform,
2647 out_snd_device,
2648 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302649 enable_audio_route_for_voice_usecases(adev, usecase);
2650 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002651
sangwoo170731f2013-06-08 15:36:36 +09002652 usecase->in_snd_device = in_snd_device;
2653 usecase->out_snd_device = out_snd_device;
2654
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302655 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2656 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302657 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002658 if ((24 == usecase->stream.out->bit_width) &&
2659 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2660 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2661 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2662 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2663 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2664 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2665 /*
2666 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2667 * configured device sample rate, if not update the COPP rate to be equal to the
2668 * device sample rate, else open COPP at stream sample rate
2669 */
2670 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2671 usecase->stream.out->sample_rate,
2672 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302673 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2674 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002675 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2676 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2677 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2678 }
2679
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002680 /* Notify device change info to effect clients registered */
2681 audio_extn_gef_notify_device_config(
2682 usecase->stream.out->devices,
2683 usecase->stream.out->channel_mask,
2684 usecase->stream.out->app_type_cfg.sample_rate,
2685 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302686 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002687 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002688
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002689 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002690
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002691 /* If input stream is already running then effect needs to be
2692 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002693 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002694 check_and_enable_effect(adev);
2695
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002696 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002697 /* Enable aanc only if voice call exists */
2698 if (voice_is_call_state_active(adev))
2699 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2700
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002701 /* Enable sidetone only if other voice/voip call already exists */
2702 if (voice_is_call_state_active(adev) ||
2703 voice_extn_compress_voip_is_started(adev))
2704 voice_set_sidetone(adev, out_snd_device, true);
2705 }
2706
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002707 /* Applicable only on the targets that has external modem.
2708 * Enable device command should be sent to modem only after
2709 * enabling voice call mixer controls
2710 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002711 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002712 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2713 out_snd_device,
2714 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302715
2716 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002717 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302718 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002719 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302720 if (is_bt_soc_on(adev) == false){
2721 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002722 if (in->pcm != NULL)
2723 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302724 }
2725 }
2726 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2727 && usecase->stream.out->started) {
2728 if (is_bt_soc_on(adev) == false) {
2729 ALOGD("BT SCO/A2DP disconnected while in connection");
2730 out_standby_l(&usecase->stream.out->stream.common);
2731 }
2732 }
2733 } else if ((usecase->stream.out != NULL) &&
2734 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302735 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2736 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302737 usecase->stream.out->started) {
2738 if (is_bt_soc_on(adev) == false) {
2739 ALOGD("BT SCO/A2dp disconnected while in connection");
2740 out_standby_l(&usecase->stream.out->stream.common);
2741 }
2742 }
2743 }
2744
Yung Ti Su70cb8242018-06-22 17:38:47 +08002745 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002746 struct stream_out *voip_out = voip_usecase->stream.out;
2747 audio_extn_utils_send_app_type_gain(adev,
2748 voip_out->app_type_cfg.app_type,
2749 &voip_out->app_type_cfg.gain[0]);
2750 }
2751
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302752 ALOGD("%s: done",__func__);
2753
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002754 return status;
2755}
2756
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757static int stop_input_stream(struct stream_in *in)
2758{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302759 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002760 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302761
2762 if (in == NULL) {
2763 ALOGE("%s: stream_in ptr is NULL", __func__);
2764 return -EINVAL;
2765 }
2766
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002767 struct audio_device *adev = in->dev;
Carter Hsu2e429db2019-05-14 18:50:52 +08002768 struct stream_in *priority_in = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002769
Eric Laurent994a6932013-07-17 11:51:42 -07002770 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002771 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002772 uc_info = get_usecase_from_list(adev, in->usecase);
2773 if (uc_info == NULL) {
2774 ALOGE("%s: Could not find the usecase (%d) in the list",
2775 __func__, in->usecase);
2776 return -EINVAL;
2777 }
2778
Carter Hsu2e429db2019-05-14 18:50:52 +08002779 priority_in = get_priority_input(adev);
2780
Derek Chenea197282019-01-07 17:35:01 -08002781 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2782 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002783
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002784 /* Close in-call recording streams */
2785 voice_check_and_stop_incall_rec_usecase(adev, in);
2786
Eric Laurent150dbfe2013-02-27 14:31:02 -08002787 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002788 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002789
2790 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002791 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002793 list_remove(&uc_info->list);
2794 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002795
Carter Hsu2e429db2019-05-14 18:50:52 +08002796 if (priority_in == in) {
2797 priority_in = get_priority_input(adev);
2798 if (priority_in)
2799 select_devices(adev, priority_in->usecase);
2800 }
2801
Vatsal Buchac09ae062018-11-14 13:25:08 +05302802 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002803 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002804 return ret;
2805}
2806
2807int start_input_stream(struct stream_in *in)
2808{
2809 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002810 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002811 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302812
2813 if (in == NULL) {
2814 ALOGE("%s: stream_in ptr is NULL", __func__);
2815 return -EINVAL;
2816 }
2817
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002818 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002819 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002820 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002821
Mingming Yin2664a5b2015-09-03 10:53:11 -07002822 if (get_usecase_from_list(adev, usecase) == NULL)
2823 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302824 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2825 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002826
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302827 if (CARD_STATUS_OFFLINE == in->card_status||
2828 CARD_STATUS_OFFLINE == adev->card_status) {
2829 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302830 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302831 goto error_config;
2832 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302833
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302834 if (audio_is_bluetooth_sco_device(in->device)) {
2835 if (!adev->bt_sco_on) {
2836 ALOGE("%s: SCO profile is not ready, return error", __func__);
2837 ret = -EIO;
2838 goto error_config;
2839 }
2840 }
2841
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002842 /* Check if source matches incall recording usecase criteria */
2843 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2844 if (ret)
2845 goto error_config;
2846 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002847 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2848
2849 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2850 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2851 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002852 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002853 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002854
Eric Laurentb23d5282013-05-14 15:27:20 -07002855 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002856 if (in->pcm_device_id < 0) {
2857 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2858 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002859 ret = -EINVAL;
2860 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002861 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002862
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002863 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002864
2865 if (!uc_info) {
2866 ret = -ENOMEM;
2867 goto error_config;
2868 }
2869
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002870 uc_info->id = in->usecase;
2871 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002872 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002873 uc_info->devices = in->device;
2874 uc_info->in_snd_device = SND_DEVICE_NONE;
2875 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002876
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002877 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002878 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302879 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2880 adev->perf_lock_opts,
2881 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002882 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002883
Derek Chenea197282019-01-07 17:35:01 -08002884 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2885 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002886
Haynes Mathew George16081042017-05-31 17:16:49 -07002887 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302888 ret = audio_extn_cin_start_input_stream(in);
2889 if (ret)
2890 goto error_open;
2891 else
2892 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002893 }
2894
Haynes Mathew George16081042017-05-31 17:16:49 -07002895 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002896 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002897 ALOGE("%s: pcm stream not ready", __func__);
2898 goto error_open;
2899 }
2900 ret = pcm_start(in->pcm);
2901 if (ret < 0) {
2902 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2903 goto error_open;
2904 }
2905 } else {
2906 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2907 unsigned int pcm_open_retry_count = 0;
2908
2909 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2910 flags |= PCM_MMAP | PCM_NOIRQ;
2911 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2912 } else if (in->realtime) {
2913 flags |= PCM_MMAP | PCM_NOIRQ;
2914 }
2915
Garmond Leunge2433c32017-09-28 21:51:22 -07002916 if (audio_extn_ffv_get_stream() == in) {
2917 ALOGD("%s: ffv stream, update pcm config", __func__);
2918 audio_extn_ffv_update_pcm_config(&config);
2919 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002920 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2921 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2922
2923 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002924 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002925 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002926 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002927 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302928 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302929 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2930 adev->card_status = CARD_STATUS_OFFLINE;
2931 in->card_status = CARD_STATUS_OFFLINE;
2932 ret = -EIO;
2933 goto error_open;
2934 }
2935
Haynes Mathew George16081042017-05-31 17:16:49 -07002936 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2937 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2938 if (in->pcm != NULL) {
2939 pcm_close(in->pcm);
2940 in->pcm = NULL;
2941 }
2942 if (pcm_open_retry_count-- == 0) {
2943 ret = -EIO;
2944 goto error_open;
2945 }
2946 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2947 continue;
2948 }
2949 break;
2950 }
2951
2952 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002953 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002954 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002955 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002956 if (ret < 0) {
2957 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2958 pcm_close(in->pcm);
2959 in->pcm = NULL;
2960 goto error_open;
2961 }
2962 register_in_stream(in);
2963 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002964 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002965 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002966 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002967 if (ret < 0) {
2968 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002969 pcm_close(in->pcm);
2970 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002971 goto error_open;
2972 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002973 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002974 }
2975
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002976 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07002977 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
2978 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002979
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302980done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08002981 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302982 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002983 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302984 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002985 return ret;
2986
2987error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08002988 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302989 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002990 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002991
Eric Laurentc8400632013-02-14 19:04:54 -08002992error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302993 /*
2994 * sleep 50ms to allow sufficient time for kernel
2995 * drivers to recover incases like SSR.
2996 */
2997 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002998 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302999 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08003000 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003001}
3002
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003003void lock_input_stream(struct stream_in *in)
3004{
3005 pthread_mutex_lock(&in->pre_lock);
3006 pthread_mutex_lock(&in->lock);
3007 pthread_mutex_unlock(&in->pre_lock);
3008}
3009
3010void lock_output_stream(struct stream_out *out)
3011{
3012 pthread_mutex_lock(&out->pre_lock);
3013 pthread_mutex_lock(&out->lock);
3014 pthread_mutex_unlock(&out->pre_lock);
3015}
3016
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003017/* must be called with out->lock locked */
3018static int send_offload_cmd_l(struct stream_out* out, int command)
3019{
3020 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
3021
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003022 if (!cmd) {
3023 ALOGE("failed to allocate mem for command 0x%x", command);
3024 return -ENOMEM;
3025 }
3026
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003027 ALOGVV("%s %d", __func__, command);
3028
3029 cmd->cmd = command;
3030 list_add_tail(&out->offload_cmd_list, &cmd->node);
3031 pthread_cond_signal(&out->offload_cond);
3032 return 0;
3033}
3034
3035/* must be called iwth out->lock locked */
3036static void stop_compressed_output_l(struct stream_out *out)
3037{
3038 out->offload_state = OFFLOAD_STATE_IDLE;
3039 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003040 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003041 if (out->compr != NULL) {
3042 compress_stop(out->compr);
3043 while (out->offload_thread_blocked) {
3044 pthread_cond_wait(&out->cond, &out->lock);
3045 }
3046 }
3047}
3048
Varun Balaraje49253e2017-07-06 19:48:56 +05303049bool is_interactive_usecase(audio_usecase_t uc_id)
3050{
3051 unsigned int i;
3052 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
3053 if (uc_id == interactive_usecases[i])
3054 return true;
3055 }
3056 return false;
3057}
3058
3059static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
3060{
3061 audio_usecase_t ret_uc = USECASE_INVALID;
3062 unsigned int intract_uc_index;
3063 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3064
3065 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
3066 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
3067 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
3068 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
3069 ret_uc = interactive_usecases[intract_uc_index];
3070 break;
3071 }
3072 }
3073
3074 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
3075 return ret_uc;
3076}
3077
3078static void free_interactive_usecase(struct audio_device *adev,
3079 audio_usecase_t uc_id)
3080{
3081 unsigned int interact_uc_index;
3082 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
3083
3084 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
3085 if (interactive_usecases[interact_uc_index] == uc_id) {
3086 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
3087 break;
3088 }
3089 }
3090 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
3091}
3092
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003093bool is_offload_usecase(audio_usecase_t uc_id)
3094{
3095 unsigned int i;
3096 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
3097 if (uc_id == offload_usecases[i])
3098 return true;
3099 }
3100 return false;
3101}
3102
Dhananjay Kumarac341582017-02-23 23:42:25 +05303103static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003104{
vivek mehta446c3962015-09-14 10:57:35 -07003105 audio_usecase_t ret_uc = USECASE_INVALID;
3106 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003107 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003108 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05303109 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07003110 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
3111 else
3112 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003113
vivek mehta446c3962015-09-14 10:57:35 -07003114 pthread_mutex_lock(&adev->lock);
3115 if (get_usecase_from_list(adev, ret_uc) != NULL)
3116 ret_uc = USECASE_INVALID;
3117 pthread_mutex_unlock(&adev->lock);
3118
3119 return ret_uc;
3120 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003121
3122 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003123 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3124 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3125 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3126 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003127 break;
3128 }
3129 }
vivek mehta446c3962015-09-14 10:57:35 -07003130
3131 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3132 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003133}
3134
3135static void free_offload_usecase(struct audio_device *adev,
3136 audio_usecase_t uc_id)
3137{
vivek mehta446c3962015-09-14 10:57:35 -07003138 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003139 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003140
3141 if (!adev->multi_offload_enable)
3142 return;
3143
3144 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3145 if (offload_usecases[offload_uc_index] == uc_id) {
3146 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003147 break;
3148 }
3149 }
3150 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3151}
3152
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003153static void *offload_thread_loop(void *context)
3154{
3155 struct stream_out *out = (struct stream_out *) context;
3156 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003157 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003158
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003159 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003160 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003161 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3162
3163 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003164 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003165 out->offload_state = OFFLOAD_STATE_IDLE;
3166 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003167 for (;;) {
3168 struct offload_cmd *cmd = NULL;
3169 stream_callback_event_t event;
3170 bool send_callback = false;
3171
3172 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3173 __func__, list_empty(&out->offload_cmd_list),
3174 out->offload_state);
3175 if (list_empty(&out->offload_cmd_list)) {
3176 ALOGV("%s SLEEPING", __func__);
3177 pthread_cond_wait(&out->offload_cond, &out->lock);
3178 ALOGV("%s RUNNING", __func__);
3179 continue;
3180 }
3181
3182 item = list_head(&out->offload_cmd_list);
3183 cmd = node_to_item(item, struct offload_cmd, node);
3184 list_remove(item);
3185
3186 ALOGVV("%s STATE %d CMD %d out->compr %p",
3187 __func__, out->offload_state, cmd->cmd, out->compr);
3188
3189 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3190 free(cmd);
3191 break;
3192 }
3193
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003194 // allow OFFLOAD_CMD_ERROR reporting during standby
3195 // this is needed to handle failures during compress_open
3196 // Note however that on a pause timeout, the stream is closed
3197 // and no offload usecase will be active. Therefore this
3198 // special case is needed for compress_open failures alone
3199 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3200 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003201 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003202 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003203 pthread_cond_signal(&out->cond);
3204 continue;
3205 }
3206 out->offload_thread_blocked = true;
3207 pthread_mutex_unlock(&out->lock);
3208 send_callback = false;
3209 switch(cmd->cmd) {
3210 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003211 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003212 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003213 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003214 send_callback = true;
3215 event = STREAM_CBK_EVENT_WRITE_READY;
3216 break;
3217 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003218 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303219 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003220 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303221 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003222 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303223 if (ret < 0)
3224 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303225 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303226 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003227 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003228 else
3229 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003230 if (-ENETRESET != ret && !(-EINTR == ret &&
3231 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303232 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303233 pthread_mutex_lock(&out->lock);
3234 out->send_new_metadata = 1;
3235 out->send_next_track_params = true;
3236 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303237 event = STREAM_CBK_EVENT_DRAIN_READY;
3238 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3239 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303240 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003241 break;
3242 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003243 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003244 ret = compress_drain(out->compr);
3245 ALOGD("copl(%p):out of compress_drain", out);
3246 // EINTR check avoids drain interruption due to SSR
3247 if (-ENETRESET != ret && !(-EINTR == ret &&
3248 CARD_STATUS_OFFLINE == out->card_status)) {
3249 send_callback = true;
3250 event = STREAM_CBK_EVENT_DRAIN_READY;
3251 } else
3252 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003253 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303254 case OFFLOAD_CMD_ERROR:
3255 ALOGD("copl(%p): sending error callback to AF", out);
3256 send_callback = true;
3257 event = STREAM_CBK_EVENT_ERROR;
3258 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003259 default:
3260 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3261 break;
3262 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003263 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003264 out->offload_thread_blocked = false;
3265 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003266 if (send_callback && out->client_callback) {
3267 ALOGVV("%s: sending client_callback event %d", __func__, event);
3268 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003269 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003270 free(cmd);
3271 }
3272
3273 pthread_cond_signal(&out->cond);
3274 while (!list_empty(&out->offload_cmd_list)) {
3275 item = list_head(&out->offload_cmd_list);
3276 list_remove(item);
3277 free(node_to_item(item, struct offload_cmd, node));
3278 }
3279 pthread_mutex_unlock(&out->lock);
3280
3281 return NULL;
3282}
3283
3284static int create_offload_callback_thread(struct stream_out *out)
3285{
3286 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3287 list_init(&out->offload_cmd_list);
3288 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3289 offload_thread_loop, out);
3290 return 0;
3291}
3292
3293static int destroy_offload_callback_thread(struct stream_out *out)
3294{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003295 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003296 stop_compressed_output_l(out);
3297 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3298
3299 pthread_mutex_unlock(&out->lock);
3300 pthread_join(out->offload_thread, (void **) NULL);
3301 pthread_cond_destroy(&out->offload_cond);
3302
3303 return 0;
3304}
3305
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003306static int stop_output_stream(struct stream_out *out)
3307{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303308 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003309 struct audio_usecase *uc_info;
3310 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003311 bool has_voip_usecase =
3312 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003313
Eric Laurent994a6932013-07-17 11:51:42 -07003314 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003315 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003316 uc_info = get_usecase_from_list(adev, out->usecase);
3317 if (uc_info == NULL) {
3318 ALOGE("%s: Could not find the usecase (%d) in the list",
3319 __func__, out->usecase);
3320 return -EINVAL;
3321 }
3322
Derek Chenea197282019-01-07 17:35:01 -08003323 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3324 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003325
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003326 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303327 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003328 if (adev->visualizer_stop_output != NULL)
3329 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003330
3331 audio_extn_dts_remove_state_notifier_node(out->usecase);
3332
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003333 if (adev->offload_effects_stop_output != NULL)
3334 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003335 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3336 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3337 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003338 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003339
Arun Mirpurief53ce52018-09-11 18:00:09 -07003340 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3341 voice_set_device_mute_flag(adev, false);
3342
Eric Laurent150dbfe2013-02-27 14:31:02 -08003343 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003344 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003345
3346 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003347 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003348
Aalique Grahame22e49102018-12-18 14:23:57 -08003349 audio_extn_extspk_update(adev->extspk);
3350
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003351 if (is_offload_usecase(out->usecase)) {
3352 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3353 adev->dsp_bit_width_enforce_mode,
3354 false);
3355 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003356 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3357 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3358 false);
3359
3360 if (ret != 0)
3361 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3362 /* default service interval was successfully updated,
3363 reopen USB backend with new service interval */
3364 ret = 0;
3365 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003366
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003367 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303368 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003369 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303370 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003371 ALOGV("Disable passthrough , reset mixer to pcm");
3372 /* NO_PASSTHROUGH */
3373 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003374 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003375 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3376 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003377
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303378 /* Must be called after removing the usecase from list */
3379 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303380 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303381
Manish Dewangan21a850a2017-08-14 12:03:55 +05303382 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003383 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3384 if (ret < 0)
3385 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3386 }
3387
juyuchen2d415992018-11-16 14:15:16 +08003388 /* 1) media + voip output routing to handset must route media back to
3389 speaker when voip stops.
3390 2) trigger voip input to reroute when voip output changes to
3391 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003392 if (has_voip_usecase ||
3393 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3394 struct listnode *node;
3395 struct audio_usecase *usecase;
3396 list_for_each(node, &adev->usecase_list) {
3397 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003398 if ((usecase->type == PCM_CAPTURE &&
3399 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3400 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003401 continue;
3402
3403 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3404 __func__, usecase->id, use_case_table[usecase->id],
3405 out->usecase, use_case_table[out->usecase]);
3406 select_devices(adev, usecase->id);
3407 }
3408 }
3409
Garmond Leung5fd0b552018-04-17 11:56:12 -07003410 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003411 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 return ret;
3413}
3414
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003415struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3416 unsigned int flags, unsigned int pcm_open_retry_count,
3417 struct pcm_config *config)
3418{
3419 struct pcm* pcm = NULL;
3420
3421 while (1) {
3422 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3423 if (pcm == NULL || !pcm_is_ready(pcm)) {
3424 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3425 if (pcm != NULL) {
3426 pcm_close(pcm);
3427 pcm = NULL;
3428 }
3429 if (pcm_open_retry_count-- == 0)
3430 return NULL;
3431
3432 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3433 continue;
3434 }
3435 break;
3436 }
3437
3438 if (pcm_is_ready(pcm)) {
3439 int ret = pcm_prepare(pcm);
3440 if (ret < 0) {
3441 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3442 pcm_close(pcm);
3443 pcm = NULL;
3444 }
3445 }
3446
3447 return pcm;
3448}
3449
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003450int start_output_stream(struct stream_out *out)
3451{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003452 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003453 struct audio_usecase *uc_info;
3454 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003455 char mixer_ctl_name[128];
3456 struct mixer_ctl *ctl = NULL;
3457 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303458 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003459 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003460
Haynes Mathew George380745d2017-10-04 15:27:45 -07003461 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003462 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3463 ret = -EINVAL;
3464 goto error_config;
3465 }
3466
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003467 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303468 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003469 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303470
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303471 if (CARD_STATUS_OFFLINE == out->card_status ||
3472 CARD_STATUS_OFFLINE == adev->card_status) {
3473 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303474 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303475 goto error_config;
3476 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303477
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303478 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003479 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003480 if (out->devices &
3481 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303482 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303483 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303484 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3485 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3486 ret = -EAGAIN;
3487 goto error_config;
3488 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303489 }
3490 }
3491 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303492 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3493 if (!adev->bt_sco_on) {
3494 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3495 //combo usecase just by pass a2dp
3496 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3497 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3498 } else {
3499 ALOGE("%s: SCO profile is not ready, return error", __func__);
3500 ret = -EAGAIN;
3501 goto error_config;
3502 }
3503 }
3504 }
3505
Eric Laurentb23d5282013-05-14 15:27:20 -07003506 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003507 if (out->pcm_device_id < 0) {
3508 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3509 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003510 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003511 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003512 }
3513
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003514 if (is_haptic_usecase) {
3515 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3516 if (adev->haptic_pcm_device_id < 0) {
3517 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3518 __func__, adev->haptic_pcm_device_id, out->usecase);
3519 ret = -EINVAL;
3520 goto error_config;
3521 }
3522 }
3523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003524 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003525
3526 if (!uc_info) {
3527 ret = -ENOMEM;
3528 goto error_config;
3529 }
3530
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003531 uc_info->id = out->usecase;
3532 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003533 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003534 uc_info->devices = out->devices;
3535 uc_info->in_snd_device = SND_DEVICE_NONE;
3536 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003537
3538 /* This must be called before adding this usecase to the list */
3539 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3540 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3541 /* USB backend is not reopened immediately.
3542 This is eventually done as part of select_devices */
3543 }
3544
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003545 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546
Wei Wangf7ca6c92017-11-21 14:51:20 -08003547 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303548 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3549 adev->perf_lock_opts,
3550 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303551
3552 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303553 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303554 if (audio_extn_passthru_is_enabled() &&
3555 audio_extn_passthru_is_passthrough_stream(out)) {
3556 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303557 }
3558 }
3559
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303560 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003561 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303562 if (!a2dp_combo) {
3563 check_a2dp_restore_l(adev, out, false);
3564 } else {
3565 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003566 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3567 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3568 else
3569 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303570 select_devices(adev, out->usecase);
3571 out->devices = dev;
3572 }
3573 } else {
3574 select_devices(adev, out->usecase);
3575 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003576
Arun Mirpurief53ce52018-09-11 18:00:09 -07003577 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3578 voice_set_device_mute_flag(adev, true);
3579
Derek Chenea197282019-01-07 17:35:01 -08003580 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3581 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003582
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003583 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3584 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003585
3586 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003587 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003588 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3589 ALOGE("%s: pcm stream not ready", __func__);
3590 goto error_open;
3591 }
3592 ret = pcm_start(out->pcm);
3593 if (ret < 0) {
3594 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3595 goto error_open;
3596 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003597 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003598 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003599 unsigned int flags = PCM_OUT;
3600 unsigned int pcm_open_retry_count = 0;
3601 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3602 flags |= PCM_MMAP | PCM_NOIRQ;
3603 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003604 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003605 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003606 } else
3607 flags |= PCM_MONOTONIC;
3608
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003609 if ((adev->vr_audio_mode_enabled) &&
3610 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3611 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3612 "PCM_Dev %d Topology", out->pcm_device_id);
3613 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3614 if (!ctl) {
3615 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3616 __func__, mixer_ctl_name);
3617 } else {
3618 //if success use ULLPP
3619 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3620 __func__, mixer_ctl_name, out->pcm_device_id);
3621 //There is a still a possibility that some sessions
3622 // that request for FAST|RAW when 3D audio is active
3623 //can go through ULLPP. Ideally we expects apps to
3624 //listen to audio focus and stop concurrent playback
3625 //Also, we will look for mode flag (voice_in_communication)
3626 //before enabling the realtime flag.
3627 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3628 }
3629 }
3630
Surendar Karka91fa3682018-07-02 18:12:12 +05303631 if (out->realtime)
3632 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3633 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3634
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003635 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3636 flags, pcm_open_retry_count,
3637 &(out->config));
3638 if (out->pcm == NULL) {
3639 ret = -EIO;
3640 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003641 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003642
3643 if (is_haptic_usecase) {
3644 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3645 adev->haptic_pcm_device_id,
3646 flags, pcm_open_retry_count,
3647 &(adev->haptics_config));
3648 // failure to open haptics pcm shouldnt stop audio,
3649 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003650
3651 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3652 ALOGD("%s: enable haptic audio synchronization", __func__);
3653 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3654 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003655 }
3656
Surendar Karka91fa3682018-07-02 18:12:12 +05303657 if (!out->realtime)
3658 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303659 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003660
Zhou Song2b8f28f2017-09-11 10:51:38 +08003661 // apply volume for voip playback after path is set up
3662 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3663 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303664 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3665 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303666 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3667 out->apply_volume = false;
Derek Chenf13dd492018-11-13 14:53:51 -08003668 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
3669 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303670 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003671 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003672 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303673 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003674 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3675 adev->dsp_bit_width_enforce_mode,
3676 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003678 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003679 out->compr = compress_open(adev->snd_card,
3680 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003681 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003682 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303683 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303684 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3685 adev->card_status = CARD_STATUS_OFFLINE;
3686 out->card_status = CARD_STATUS_OFFLINE;
3687 ret = -EIO;
3688 goto error_open;
3689 }
3690
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003691 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003692 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003693 compress_close(out->compr);
3694 out->compr = NULL;
3695 ret = -EIO;
3696 goto error_open;
3697 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303698 /* compress_open sends params of the track, so reset the flag here */
3699 out->is_compr_metadata_avail = false;
3700
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003701 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003702 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003703
Fred Oh3f43e742015-03-04 18:42:34 -08003704 /* Since small bufs uses blocking writes, a write will be blocked
3705 for the default max poll time (20s) in the event of an SSR.
3706 Reduce the poll time to observe and deal with SSR faster.
3707 */
Ashish Jain5106d362016-05-11 19:23:33 +05303708 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003709 compress_set_max_poll_wait(out->compr, 1000);
3710 }
3711
Manish Dewangan69426c82017-01-30 17:35:36 +05303712 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303713 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303714
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003715 audio_extn_dts_create_state_notifier_node(out->usecase);
3716 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3717 popcount(out->channel_mask),
3718 out->playback_started);
3719
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003720#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303721 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003722 audio_extn_dolby_send_ddp_endp_params(adev);
3723#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303724 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3725 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003726 if (adev->visualizer_start_output != NULL)
3727 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3728 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303729 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003730 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003731 }
Derek Chenf13dd492018-11-13 14:53:51 -08003732
3733 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
3734 /* Update cached volume from media to offload/direct stream */
3735 struct listnode *node = NULL;
3736 list_for_each(node, &adev->active_outputs_list) {
3737 streams_output_ctxt_t *out_ctxt = node_to_item(node,
3738 streams_output_ctxt_t,
3739 list);
3740 if (out_ctxt->output->usecase == USECASE_AUDIO_PLAYBACK_MEDIA) {
3741 out->volume_l = out_ctxt->output->volume_l;
3742 out->volume_r = out_ctxt->output->volume_r;
3743 }
3744 }
3745 out_set_compr_volume(&out->stream,
3746 out->volume_l, out->volume_r);
3747 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003748 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003749
3750 if (ret == 0) {
3751 register_out_stream(out);
3752 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003753 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3754 ALOGE("%s: pcm stream not ready", __func__);
3755 goto error_open;
3756 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003757 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003758 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003759 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003760 if (ret < 0)
3761 goto error_open;
3762 }
3763 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003764 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303765 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003766 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003767
vivek mehtad15d2bf2019-05-17 13:35:10 -07003768 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3769 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3770 audio_low_latency_hint_start();
3771 }
3772
Manish Dewangan21a850a2017-08-14 12:03:55 +05303773 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003774 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003775 if (ret < 0)
3776 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3777 }
3778
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003779 // consider a scenario where on pause lower layers are tear down.
3780 // so on resume, swap mixer control need to be sent only when
3781 // backend is active, hence rather than sending from enable device
3782 // sending it from start of streamtream
3783
3784 platform_set_swap_channels(adev, true);
3785
Haynes Mathew George380745d2017-10-04 15:27:45 -07003786 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303787 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003788 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003789error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003790 if (adev->haptic_pcm) {
3791 pcm_close(adev->haptic_pcm);
3792 adev->haptic_pcm = NULL;
3793 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003794 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303795 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003796 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003797error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303798 /*
3799 * sleep 50ms to allow sufficient time for kernel
3800 * drivers to recover incases like SSR.
3801 */
3802 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003803 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303804 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003805 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003806}
3807
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003808static int check_input_parameters(uint32_t sample_rate,
3809 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003810 int channel_count,
3811 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003812{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003813 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303815 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3816 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3817 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003818 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003819 !audio_extn_compr_cap_format_supported(format) &&
3820 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003821 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003822
Aalique Grahame22e49102018-12-18 14:23:57 -08003823 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3824 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3825 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3826 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3827 return -EINVAL;
3828 }
3829
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003830 switch (channel_count) {
3831 case 1:
3832 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303833 case 3:
3834 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003835 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003836 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003837 break;
3838 default:
3839 ret = -EINVAL;
3840 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003841
3842 switch (sample_rate) {
3843 case 8000:
3844 case 11025:
3845 case 12000:
3846 case 16000:
3847 case 22050:
3848 case 24000:
3849 case 32000:
3850 case 44100:
3851 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003852 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303853 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003854 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303855 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003856 break;
3857 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003858 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003859 }
3860
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003861 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003862}
3863
Naresh Tanniru04f71882018-06-26 17:46:22 +05303864
3865/** Add a value in a list if not already present.
3866 * @return true if value was successfully inserted or already present,
3867 * false if the list is full and does not contain the value.
3868 */
3869static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3870 for (size_t i = 0; i < list_length; i++) {
3871 if (list[i] == value) return true; // value is already present
3872 if (list[i] == 0) { // no values in this slot
3873 list[i] = value;
3874 return true; // value inserted
3875 }
3876 }
3877 return false; // could not insert value
3878}
3879
3880/** Add channel_mask in supported_channel_masks if not already present.
3881 * @return true if channel_mask was successfully inserted or already present,
3882 * false if supported_channel_masks is full and does not contain channel_mask.
3883 */
3884static void register_channel_mask(audio_channel_mask_t channel_mask,
3885 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3886 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3887 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3888}
3889
3890/** Add format in supported_formats if not already present.
3891 * @return true if format was successfully inserted or already present,
3892 * false if supported_formats is full and does not contain format.
3893 */
3894static void register_format(audio_format_t format,
3895 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3896 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3897 "%s: stream can not declare supporting its format %x", __func__, format);
3898}
3899/** Add sample_rate in supported_sample_rates if not already present.
3900 * @return true if sample_rate was successfully inserted or already present,
3901 * false if supported_sample_rates is full and does not contain sample_rate.
3902 */
3903static void register_sample_rate(uint32_t sample_rate,
3904 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3905 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3906 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3907}
3908
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003909static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3910{
3911 uint32_t high = num1, low = num2, temp = 0;
3912
3913 if (!num1 || !num2)
3914 return 0;
3915
3916 if (num1 < num2) {
3917 high = num2;
3918 low = num1;
3919 }
3920
3921 while (low != 0) {
3922 temp = low;
3923 low = high % low;
3924 high = temp;
3925 }
3926 return (num1 * num2)/high;
3927}
3928
3929static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3930{
3931 uint32_t remainder = 0;
3932
3933 if (!multiplier)
3934 return num;
3935
3936 remainder = num % multiplier;
3937 if (remainder)
3938 num += (multiplier - remainder);
3939
3940 return num;
3941}
3942
Aalique Grahame22e49102018-12-18 14:23:57 -08003943static size_t get_stream_buffer_size(size_t duration_ms,
3944 uint32_t sample_rate,
3945 audio_format_t format,
3946 int channel_count,
3947 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003948{
3949 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003950 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003951
Aalique Grahame22e49102018-12-18 14:23:57 -08003952 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003953 if (is_low_latency)
3954 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303955
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003956 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003957 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003958
Ralf Herzbd08d632018-09-28 15:50:49 +02003959 /* make sure the size is multiple of 32 bytes and additionally multiple of
3960 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003961 * At 48 kHz mono 16-bit PCM:
3962 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3963 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003964 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003965 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003966 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003967
3968 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003969}
3970
Aalique Grahame22e49102018-12-18 14:23:57 -08003971static size_t get_input_buffer_size(uint32_t sample_rate,
3972 audio_format_t format,
3973 int channel_count,
3974 bool is_low_latency)
3975{
3976 /* Don't know if USB HIFI in this context so use true to be conservative */
3977 if (check_input_parameters(sample_rate, format, channel_count,
3978 true /*is_usb_hifi */) != 0)
3979 return 0;
3980
3981 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3982 sample_rate,
3983 format,
3984 channel_count,
3985 is_low_latency);
3986}
3987
Derek Chenf6318be2017-06-12 17:16:24 -04003988size_t get_output_period_size(uint32_t sample_rate,
3989 audio_format_t format,
3990 int channel_count,
3991 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05303992{
3993 size_t size = 0;
3994 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3995
3996 if ((duration == 0) || (sample_rate == 0) ||
3997 (bytes_per_sample == 0) || (channel_count == 0)) {
3998 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3999 bytes_per_sample, channel_count);
4000 return -EINVAL;
4001 }
4002
4003 size = (sample_rate *
4004 duration *
4005 bytes_per_sample *
4006 channel_count) / 1000;
4007 /*
4008 * To have same PCM samples for all channels, the buffer size requires to
4009 * be multiple of (number of channels * bytes per sample)
4010 * For writes to succeed, the buffer must be written at address which is multiple of 32
4011 */
4012 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
4013
4014 return (size/(channel_count * bytes_per_sample));
4015}
4016
Zhou Song48453a02018-01-10 17:50:59 +08004017static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05304018{
4019 uint64_t actual_frames_rendered = 0;
4020 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
4021
4022 /* This adjustment accounts for buffering after app processor.
4023 * It is based on estimated DSP latency per use case, rather than exact.
4024 */
4025 int64_t platform_latency = platform_render_latency(out->usecase) *
4026 out->sample_rate / 1000000LL;
4027
Zhou Song48453a02018-01-10 17:50:59 +08004028 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304029 /* not querying actual state of buffering in kernel as it would involve an ioctl call
4030 * which then needs protection, this causes delay in TS query for pcm_offload usecase
4031 * hence only estimate.
4032 */
4033 int64_t signed_frames = out->written - kernel_buffer_size;
4034
4035 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
4036
Zhou Song48453a02018-01-10 17:50:59 +08004037 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05304038 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08004039 if (timestamp != NULL )
4040 *timestamp = out->writeAt;
4041 } else if (timestamp != NULL) {
4042 clock_gettime(CLOCK_MONOTONIC, timestamp);
4043 }
4044 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05304045
4046 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
4047 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
4048 (long long int)out->written, (int)kernel_buffer_size,
4049 audio_bytes_per_sample(out->compr_config.codec->format),
4050 popcount(out->channel_mask));
4051
4052 return actual_frames_rendered;
4053}
4054
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004055static uint32_t out_get_sample_rate(const struct audio_stream *stream)
4056{
4057 struct stream_out *out = (struct stream_out *)stream;
4058
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004059 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004060}
4061
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004062static int out_set_sample_rate(struct audio_stream *stream __unused,
4063 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004064{
4065 return -ENOSYS;
4066}
4067
4068static size_t out_get_buffer_size(const struct audio_stream *stream)
4069{
4070 struct stream_out *out = (struct stream_out *)stream;
4071
Varun Balaraje49253e2017-07-06 19:48:56 +05304072 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05304073 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05304074 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05304075 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
4076 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
4077 else
4078 return out->compr_config.fragment_size;
4079 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004080 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004081 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
4082 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 +05304083 else if (is_offload_usecase(out->usecase) &&
4084 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05304085 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004086
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004087 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07004088 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004089}
4090
4091static uint32_t out_get_channels(const struct audio_stream *stream)
4092{
4093 struct stream_out *out = (struct stream_out *)stream;
4094
4095 return out->channel_mask;
4096}
4097
4098static audio_format_t out_get_format(const struct audio_stream *stream)
4099{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004100 struct stream_out *out = (struct stream_out *)stream;
4101
4102 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004103}
4104
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07004105static int out_set_format(struct audio_stream *stream __unused,
4106 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004107{
4108 return -ENOSYS;
4109}
4110
4111static int out_standby(struct audio_stream *stream)
4112{
4113 struct stream_out *out = (struct stream_out *)stream;
4114 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07004115 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004116
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05304117 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4118 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004119
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004120 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004121 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07004122 if (adev->adm_deregister_stream)
4123 adev->adm_deregister_stream(adev->adm_data, out->handle);
4124
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07004125 if (is_offload_usecase(out->usecase))
4126 stop_compressed_output_l(out);
4127
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08004128 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08004130 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4131 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304132 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08004133 pthread_mutex_unlock(&adev->lock);
4134 pthread_mutex_unlock(&out->lock);
4135 ALOGD("VOIP output entered standby");
4136 return 0;
4137 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004138 if (out->pcm) {
4139 pcm_close(out->pcm);
4140 out->pcm = NULL;
4141 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004142 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4143 do_stop = out->playback_started;
4144 out->playback_started = false;
4145 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004146 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004147 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304148 out->send_next_track_params = false;
4149 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004150 out->gapless_mdata.encoder_delay = 0;
4151 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004152 if (out->compr != NULL) {
4153 compress_close(out->compr);
4154 out->compr = NULL;
4155 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004156 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004157 if (do_stop) {
4158 stop_output_stream(out);
4159 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004160 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004161 }
4162 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304163 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004164 return 0;
4165}
4166
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304167static int out_on_error(struct audio_stream *stream)
4168{
4169 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004170 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304171
4172 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004173 // always send CMD_ERROR for offload streams, this
4174 // is needed e.g. when SSR happens within compress_open
4175 // since the stream is active, offload_callback_thread is also active.
4176 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4177 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004178 }
4179 pthread_mutex_unlock(&out->lock);
4180
4181 status = out_standby(&out->stream.common);
4182
4183 lock_output_stream(out);
4184 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004185 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304186 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304187
4188 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4189 ALOGD("Setting previous card status if offline");
4190 out->prev_card_status_offline = true;
4191 }
4192
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304193 pthread_mutex_unlock(&out->lock);
4194
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004195 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304196}
4197
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304198/*
4199 *standby implementation without locks, assumes that the callee already
4200 *has taken adev and out lock.
4201 */
4202int out_standby_l(struct audio_stream *stream)
4203{
4204 struct stream_out *out = (struct stream_out *)stream;
4205 struct audio_device *adev = out->dev;
4206
4207 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4208 stream, out->usecase, use_case_table[out->usecase]);
4209
4210 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004211 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304212 if (adev->adm_deregister_stream)
4213 adev->adm_deregister_stream(adev->adm_data, out->handle);
4214
4215 if (is_offload_usecase(out->usecase))
4216 stop_compressed_output_l(out);
4217
4218 out->standby = true;
4219 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4220 voice_extn_compress_voip_close_output_stream(stream);
4221 out->started = 0;
4222 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004223 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304224 return 0;
4225 } else if (!is_offload_usecase(out->usecase)) {
4226 if (out->pcm) {
4227 pcm_close(out->pcm);
4228 out->pcm = NULL;
4229 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004230 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4231 if (adev->haptic_pcm) {
4232 pcm_close(adev->haptic_pcm);
4233 adev->haptic_pcm = NULL;
4234 }
4235
4236 if (adev->haptic_buffer != NULL) {
4237 free(adev->haptic_buffer);
4238 adev->haptic_buffer = NULL;
4239 adev->haptic_buffer_size = 0;
4240 }
4241 adev->haptic_pcm_device_id = 0;
4242 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304243 } else {
4244 ALOGD("copl(%p):standby", out);
4245 out->send_next_track_params = false;
4246 out->is_compr_metadata_avail = false;
4247 out->gapless_mdata.encoder_delay = 0;
4248 out->gapless_mdata.encoder_padding = 0;
4249 if (out->compr != NULL) {
4250 compress_close(out->compr);
4251 out->compr = NULL;
4252 }
4253 }
4254 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004255 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304256 }
4257 ALOGD("%s: exit", __func__);
4258 return 0;
4259}
4260
Aalique Grahame22e49102018-12-18 14:23:57 -08004261static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004262{
Aalique Grahame22e49102018-12-18 14:23:57 -08004263 struct stream_out *out = (struct stream_out *)stream;
4264
4265 // We try to get the lock for consistency,
4266 // but it isn't necessary for these variables.
4267 // If we're not in standby, we may be blocked on a write.
4268 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4269 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4270 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4271
4272 if (locked) {
4273 pthread_mutex_unlock(&out->lock);
4274 }
4275
4276 // dump error info
4277 (void)error_log_dump(
4278 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4279
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004280 return 0;
4281}
4282
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004283static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4284{
4285 int ret = 0;
4286 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004287
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004288 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004289 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004290 return -EINVAL;
4291 }
4292
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304293 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004294
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004295 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4296 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304297 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004298 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004299 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4300 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304301 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004302 }
4303
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004304 ALOGV("%s new encoder delay %u and padding %u", __func__,
4305 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4306
4307 return 0;
4308}
4309
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004310static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4311{
4312 return out == adev->primary_output || out == adev->voice_tx_output;
4313}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004314
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304315// note: this call is safe only if the stream_cb is
4316// removed first in close_output_stream (as is done now).
4317static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4318{
4319 if (!stream || !parms)
4320 return;
4321
4322 struct stream_out *out = (struct stream_out *)stream;
4323 struct audio_device *adev = out->dev;
4324
4325 card_status_t status;
4326 int card;
4327 if (parse_snd_card_status(parms, &card, &status) < 0)
4328 return;
4329
4330 pthread_mutex_lock(&adev->lock);
4331 bool valid_cb = (card == adev->snd_card);
4332 pthread_mutex_unlock(&adev->lock);
4333
4334 if (!valid_cb)
4335 return;
4336
4337 lock_output_stream(out);
4338 if (out->card_status != status)
4339 out->card_status = status;
4340 pthread_mutex_unlock(&out->lock);
4341
4342 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4343 use_case_table[out->usecase],
4344 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4345
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304346 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304347 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304348 if (voice_is_call_state_active(adev) &&
4349 out == adev->primary_output) {
4350 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4351 pthread_mutex_lock(&adev->lock);
4352 voice_stop_call(adev);
4353 adev->mode = AUDIO_MODE_NORMAL;
4354 pthread_mutex_unlock(&adev->lock);
4355 }
4356 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304357 return;
4358}
4359
Kevin Rocardfce19002017-08-07 19:21:36 -07004360static int get_alive_usb_card(struct str_parms* parms) {
4361 int card;
4362 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4363 !audio_extn_usb_alive(card)) {
4364 return card;
4365 }
4366 return -ENODEV;
4367}
4368
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004369static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4370{
4371 struct stream_out *out = (struct stream_out *)stream;
4372 struct audio_device *adev = out->dev;
4373 struct str_parms *parms;
4374 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004375 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304376 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004377 bool reconfig = false;
4378 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004379
sangwoobc677242013-08-08 16:53:43 +09004380 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004381 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004382 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304383 if (!parms)
4384 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004385 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4386 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004387 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004388 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004389 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004390
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004391 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004392 * When HDMI cable is unplugged the music playback is paused and
4393 * the policy manager sends routing=0. But the audioflinger continues
4394 * to write data until standby time (3sec). As the HDMI core is
4395 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004396 * Avoid this by routing audio to speaker until standby.
4397 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004398 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4399 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304400 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004401 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4402 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004403 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304404 /*
4405 * When A2DP is disconnected the
4406 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004407 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304408 * (3sec). As BT is turned off, the write gets blocked.
4409 * Avoid this by routing audio to speaker until standby.
4410 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004411 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004412 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004413 !audio_extn_a2dp_source_is_ready() &&
4414 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304415 val = AUDIO_DEVICE_OUT_SPEAKER;
4416 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304417 /*
4418 * When USB headset is disconnected the music platback paused
4419 * and the policy manager send routing=0. But if the USB is connected
4420 * back before the standby time, AFE is not closed and opened
4421 * when USB is connected back. So routing to speker will guarantee
4422 * AFE reconfiguration and AFE will be opend once USB is connected again
4423 */
4424 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4425 (val == AUDIO_DEVICE_NONE) &&
4426 !audio_extn_usb_connected(parms)) {
4427 val = AUDIO_DEVICE_OUT_SPEAKER;
4428 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304429 /* To avoid a2dp to sco overlapping / BT device improper state
4430 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304431 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304432 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004433 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004434 if (val &
4435 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304436 //combo usecase just by pass a2dp
4437 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304438 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304439 } else {
4440 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4441 /* update device to a2dp and don't route as BT returned error
4442 * However it is still possible a2dp routing called because
4443 * of current active device disconnection (like wired headset)
4444 */
4445 out->devices = val;
4446 pthread_mutex_unlock(&out->lock);
4447 pthread_mutex_unlock(&adev->lock);
4448 goto error;
4449 }
4450 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304451 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004452
4453 audio_devices_t new_dev = val;
4454
4455 // Workaround: If routing to an non existing usb device, fail gracefully
4456 // The routing request will otherwise block during 10 second
4457 int card;
4458 if (audio_is_usb_out_device(new_dev) &&
4459 (card = get_alive_usb_card(parms)) >= 0) {
4460
4461 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4462 pthread_mutex_unlock(&adev->lock);
4463 pthread_mutex_unlock(&out->lock);
4464 ret = -ENOSYS;
4465 goto routing_fail;
4466 }
4467
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004468 /*
4469 * select_devices() call below switches all the usecases on the same
4470 * backend to the new device. Refer to check_usecases_codec_backend() in
4471 * the select_devices(). But how do we undo this?
4472 *
4473 * For example, music playback is active on headset (deep-buffer usecase)
4474 * and if we go to ringtones and select a ringtone, low-latency usecase
4475 * will be started on headset+speaker. As we can't enable headset+speaker
4476 * and headset devices at the same time, select_devices() switches the music
4477 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4478 * So when the ringtone playback is completed, how do we undo the same?
4479 *
4480 * We are relying on the out_set_parameters() call on deep-buffer output,
4481 * once the ringtone playback is ended.
4482 * NOTE: We should not check if the current devices are same as new devices.
4483 * Because select_devices() must be called to switch back the music
4484 * playback to headset.
4485 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004486 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004487 audio_devices_t new_dev = val;
4488 bool same_dev = out->devices == new_dev;
4489 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004490
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004491 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004492 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004493 if (adev->mode == AUDIO_MODE_IN_CALL) {
4494 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004495 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4496 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4497 audio_extn_usb_set_service_interval(true /*playback*/,
4498 service_interval,
4499 &reconfig);
4500 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4501 }
4502 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004503 }
4504 } else {
4505 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004506 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004507 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004508 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004509
4510 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004511 if (!same_dev) {
4512 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304513 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4514 adev->perf_lock_opts,
4515 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004516 if (adev->adm_on_routing_change)
4517 adev->adm_on_routing_change(adev->adm_data,
4518 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004519 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304520 if (!bypass_a2dp) {
4521 select_devices(adev, out->usecase);
4522 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004523 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4524 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4525 else
4526 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304527 select_devices(adev, out->usecase);
4528 out->devices = new_dev;
4529 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004530
4531 if (!same_dev) {
4532 // on device switch force swap, lower functions will make sure
4533 // to check if swap is allowed or not.
4534 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304535 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004536 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304537 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4538 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004539 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304540 pthread_mutex_lock(&out->compr_mute_lock);
4541 out->a2dp_compress_mute = false;
4542 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4543 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004544 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4545 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304546 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004547 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004548 }
4549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004550 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004551 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004552
4553 /*handles device and call state changes*/
4554 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004555 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004556 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004557
4558 if (out == adev->primary_output) {
4559 pthread_mutex_lock(&adev->lock);
4560 audio_extn_set_parameters(adev, parms);
4561 pthread_mutex_unlock(&adev->lock);
4562 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004563 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004564 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004565 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004566
4567 audio_extn_dts_create_state_notifier_node(out->usecase);
4568 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4569 popcount(out->channel_mask),
4570 out->playback_started);
4571
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004572 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004573 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004574
Surendar Karkaf51b5842018-04-26 11:28:38 +05304575 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4576 sizeof(value));
4577 if (err >= 0) {
4578 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4579 audio_extn_send_dual_mono_mixing_coefficients(out);
4580 }
4581
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304582 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4583 if (err >= 0) {
4584 strlcpy(out->profile, value, sizeof(out->profile));
4585 ALOGV("updating stream profile with value '%s'", out->profile);
4586 lock_output_stream(out);
4587 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4588 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004589 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304590 out->sample_rate, out->bit_width,
4591 out->channel_mask, out->profile,
4592 &out->app_type_cfg);
4593 pthread_mutex_unlock(&out->lock);
4594 }
4595
Alexy Joseph98988832017-01-13 14:56:59 -08004596 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004597 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4598 // and vendor.audio.hal.output.suspend.supported is set to true
4599 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004600 //check suspend parameter only for low latency and if the property
4601 //is enabled
4602 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4603 ALOGI("%s: got suspend_playback %s", __func__, value);
4604 lock_output_stream(out);
4605 if (!strncmp(value, "false", 5)) {
4606 //suspend_playback=false is supposed to set QOS value back to 75%
4607 //the mixer control sent with value Enable will achieve that
4608 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4609 } else if (!strncmp (value, "true", 4)) {
4610 //suspend_playback=true is supposed to remove QOS value
4611 //resetting the mixer control will set the default value
4612 //for the mixer control which is Disable and this removes the QOS vote
4613 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4614 } else {
4615 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4616 " got %s", __func__, value);
4617 ret = -1;
4618 }
4619
4620 if (ret != 0) {
4621 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4622 __func__, out->pm_qos_mixer_path, ret);
4623 }
4624
4625 pthread_mutex_unlock(&out->lock);
4626 }
4627 }
4628 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004629 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304630error:
Eric Laurent994a6932013-07-17 11:51:42 -07004631 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004632 return ret;
4633}
4634
Paul McLeana50b7332018-12-17 08:24:21 -07004635static int in_set_microphone_direction(const struct audio_stream_in *stream,
4636 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004637 struct stream_in *in = (struct stream_in *)stream;
4638
4639 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4640
4641 in->direction = dir;
4642
4643 if (in->standby)
4644 return 0;
4645
4646 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004647}
4648
4649static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004650 struct stream_in *in = (struct stream_in *)stream;
4651
4652 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4653
4654 if (zoom > 1.0 || zoom < -1.0)
4655 return -EINVAL;
4656
4657 in->zoom = zoom;
4658
4659 if (in->standby)
4660 return 0;
4661
4662 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004663}
4664
4665
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004666static bool stream_get_parameter_channels(struct str_parms *query,
4667 struct str_parms *reply,
4668 audio_channel_mask_t *supported_channel_masks) {
4669 int ret = -1;
4670 char value[512];
4671 bool first = true;
4672 size_t i, j;
4673
4674 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4675 ret = 0;
4676 value[0] = '\0';
4677 i = 0;
4678 while (supported_channel_masks[i] != 0) {
4679 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4680 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4681 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304682 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004683
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304684 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004685 first = false;
4686 break;
4687 }
4688 }
4689 i++;
4690 }
4691 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4692 }
4693 return ret == 0;
4694}
4695
4696static bool stream_get_parameter_formats(struct str_parms *query,
4697 struct str_parms *reply,
4698 audio_format_t *supported_formats) {
4699 int ret = -1;
4700 char value[256];
4701 size_t i, j;
4702 bool first = true;
4703
4704 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4705 ret = 0;
4706 value[0] = '\0';
4707 i = 0;
4708 while (supported_formats[i] != 0) {
4709 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4710 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4711 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304712 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004713 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304714 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004715 first = false;
4716 break;
4717 }
4718 }
4719 i++;
4720 }
4721 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4722 }
4723 return ret == 0;
4724}
4725
4726static bool stream_get_parameter_rates(struct str_parms *query,
4727 struct str_parms *reply,
4728 uint32_t *supported_sample_rates) {
4729
4730 int i;
4731 char value[256];
4732 int ret = -1;
4733 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4734 ret = 0;
4735 value[0] = '\0';
4736 i=0;
4737 int cursor = 0;
4738 while (supported_sample_rates[i]) {
4739 int avail = sizeof(value) - cursor;
4740 ret = snprintf(value + cursor, avail, "%s%d",
4741 cursor > 0 ? "|" : "",
4742 supported_sample_rates[i]);
4743 if (ret < 0 || ret >= avail) {
4744 // if cursor is at the last element of the array
4745 // overwrite with \0 is duplicate work as
4746 // snprintf already put a \0 in place.
4747 // else
4748 // we had space to write the '|' at value[cursor]
4749 // (which will be overwritten) or no space to fill
4750 // the first element (=> cursor == 0)
4751 value[cursor] = '\0';
4752 break;
4753 }
4754 cursor += ret;
4755 ++i;
4756 }
4757 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4758 value);
4759 }
4760 return ret >= 0;
4761}
4762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004763static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4764{
4765 struct stream_out *out = (struct stream_out *)stream;
4766 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004767 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004768 char value[256];
4769 struct str_parms *reply = str_parms_create();
4770 size_t i, j;
4771 int ret;
4772 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004773
4774 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004775 if (reply) {
4776 str_parms_destroy(reply);
4777 }
4778 if (query) {
4779 str_parms_destroy(query);
4780 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004781 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4782 return NULL;
4783 }
4784
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004785 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004786 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4787 if (ret >= 0) {
4788 value[0] = '\0';
4789 i = 0;
4790 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004791 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4792 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004793 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004794 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004795 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004796 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004797 first = false;
4798 break;
4799 }
4800 }
4801 i++;
4802 }
4803 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4804 str = str_parms_to_str(reply);
4805 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004806 voice_extn_out_get_parameters(out, query, reply);
4807 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004808 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004809
Alexy Joseph62142aa2015-11-16 15:10:34 -08004810
4811 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4812 if (ret >= 0) {
4813 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304814 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4815 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004816 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304817 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004818 } else {
4819 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304820 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004821 }
4822 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004823 if (str)
4824 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004825 str = str_parms_to_str(reply);
4826 }
4827
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004828 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4829 if (ret >= 0) {
4830 value[0] = '\0';
4831 i = 0;
4832 first = true;
4833 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004834 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4835 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004836 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004837 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004838 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004839 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004840 first = false;
4841 break;
4842 }
4843 }
4844 i++;
4845 }
4846 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004847 if (str)
4848 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004849 str = str_parms_to_str(reply);
4850 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004851
4852 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4853 if (ret >= 0) {
4854 value[0] = '\0';
4855 i = 0;
4856 first = true;
4857 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004858 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4859 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004860 if (!first) {
4861 strlcat(value, "|", sizeof(value));
4862 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004863 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004864 first = false;
4865 break;
4866 }
4867 }
4868 i++;
4869 }
4870 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4871 if (str)
4872 free(str);
4873 str = str_parms_to_str(reply);
4874 }
4875
Alexy Joseph98988832017-01-13 14:56:59 -08004876 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4877 //only low latency track supports suspend_resume
4878 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004879 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004880 if (str)
4881 free(str);
4882 str = str_parms_to_str(reply);
4883 }
4884
4885
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004886 str_parms_destroy(query);
4887 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004888 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004889 return str;
4890}
4891
4892static uint32_t out_get_latency(const struct audio_stream_out *stream)
4893{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004894 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004895 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004896 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004897
Alexy Josephaa54c872014-12-03 02:46:47 -08004898 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304899 lock_output_stream(out);
4900 latency = audio_extn_utils_compress_get_dsp_latency(out);
4901 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004902 } else if ((out->realtime) ||
4903 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004904 // since the buffer won't be filled up faster than realtime,
4905 // return a smaller number
4906 if (out->config.rate)
4907 period_ms = (out->af_period_multiplier * out->config.period_size *
4908 1000) / (out->config.rate);
4909 else
4910 period_ms = 0;
4911 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004912 } else {
4913 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004914 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004915 }
4916
yidongh0515e042017-07-06 15:00:34 +08004917 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004918 latency += audio_extn_a2dp_get_encoder_latency();
4919
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304920 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004921 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004922}
4923
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304924static float AmpToDb(float amplification)
4925{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304926 float db = DSD_VOLUME_MIN_DB;
4927 if (amplification > 0) {
4928 db = 20 * log10(amplification);
4929 if(db < DSD_VOLUME_MIN_DB)
4930 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304931 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304932 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304933}
4934
Arun Mirpuri5d170872019-03-26 13:21:31 -07004935static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4936 float right)
4937{
4938 struct stream_out *out = (struct stream_out *)stream;
4939 long volume = 0;
4940 char mixer_ctl_name[128] = "";
4941 struct audio_device *adev = out->dev;
4942 struct mixer_ctl *ctl = NULL;
4943 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4944 PCM_PLAYBACK);
4945
4946 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4947 "Playback %d Volume", pcm_device_id);
4948 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4949 if (!ctl) {
4950 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4951 __func__, mixer_ctl_name);
4952 return -EINVAL;
4953 }
4954 if (left != right)
4955 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4956 __func__, left, right);
4957 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4958 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4959 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4960 __func__, mixer_ctl_name, volume);
4961 return -EINVAL;
4962 }
4963 return 0;
4964}
4965
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304966static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4967 float right)
4968{
4969 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304970 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304971 char mixer_ctl_name[128];
4972 struct audio_device *adev = out->dev;
4973 struct mixer_ctl *ctl;
4974 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4975 PCM_PLAYBACK);
4976
4977 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4978 "Compress Playback %d Volume", pcm_device_id);
4979 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4980 if (!ctl) {
4981 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4982 __func__, mixer_ctl_name);
4983 return -EINVAL;
4984 }
4985 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4986 __func__, mixer_ctl_name, left, right);
4987 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4988 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4989 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4990
4991 return 0;
4992}
4993
Zhou Song2b8f28f2017-09-11 10:51:38 +08004994static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4995 float right)
4996{
4997 struct stream_out *out = (struct stream_out *)stream;
4998 char mixer_ctl_name[] = "App Type Gain";
4999 struct audio_device *adev = out->dev;
5000 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305001 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08005002
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07005003 if (!is_valid_volume(left, right)) {
5004 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
5005 __func__, left, right);
5006 return -EINVAL;
5007 }
5008
Zhou Song2b8f28f2017-09-11 10:51:38 +08005009 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5010 if (!ctl) {
5011 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5012 __func__, mixer_ctl_name);
5013 return -EINVAL;
5014 }
5015
5016 set_values[0] = 0; //0: Rx Session 1:Tx Session
5017 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05305018 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
5019 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005020
5021 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
5022 return 0;
5023}
5024
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305025static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
5026 float right)
5027{
5028 struct stream_out *out = (struct stream_out *)stream;
5029 /* Volume control for pcm playback */
5030 if (left != right) {
5031 return -EINVAL;
5032 } else {
5033 char mixer_ctl_name[128];
5034 struct audio_device *adev = out->dev;
5035 struct mixer_ctl *ctl;
5036 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5037 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
5038 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5039 if (!ctl) {
5040 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
5041 return -EINVAL;
5042 }
5043
5044 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
5045 int ret = mixer_ctl_set_value(ctl, 0, volume);
5046 if (ret < 0) {
5047 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
5048 return -EINVAL;
5049 }
5050
5051 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
5052
5053 return 0;
5054 }
5055}
5056
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005057static int out_set_volume(struct audio_stream_out *stream, float left,
5058 float right)
5059{
Eric Laurenta9024de2013-04-04 09:19:12 -07005060 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005061 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305062 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005063
Arun Mirpuri5d170872019-03-26 13:21:31 -07005064 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07005065 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
5066 /* only take left channel into account: the API is for stereo anyway */
5067 out->muted = (left == 0.0f);
5068 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005069 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305070 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005071 /*
5072 * Set mute or umute on HDMI passthrough stream.
5073 * Only take left channel into account.
5074 * Mute is 0 and unmute 1
5075 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305076 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305077 } else if (out->format == AUDIO_FORMAT_DSD){
5078 char mixer_ctl_name[128] = "DSD Volume";
5079 struct audio_device *adev = out->dev;
5080 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
5081
5082 if (!ctl) {
5083 ALOGE("%s: Could not get ctl for mixer cmd - %s",
5084 __func__, mixer_ctl_name);
5085 return -EINVAL;
5086 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05305087 volume[0] = (long)(AmpToDb(left));
5088 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05305089 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
5090 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07005091 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305092 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005093 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305094 if (!out->a2dp_compress_mute)
5095 ret = out_set_compr_volume(stream, left, right);
5096 out->volume_l = left;
5097 out->volume_r = right;
5098 pthread_mutex_unlock(&out->compr_mute_lock);
5099 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005100 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005101 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005102 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
5103 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
5104 if (!out->standby) {
5105 audio_extn_utils_send_app_type_gain(out->dev,
5106 out->app_type_cfg.app_type,
5107 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08005108 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08005109 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08005110 out->volume_l = left;
5111 out->volume_r = right;
5112 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005113 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5114 ALOGV("%s: MMAP set volume called", __func__);
5115 if (!out->standby)
5116 ret = out_set_mmap_volume(stream, left, right);
5117 out->volume_l = left;
5118 out->volume_r = right;
5119 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305120 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05305121 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
5122 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05305123 /* Volume control for pcm playback */
5124 if (!out->standby)
5125 ret = out_set_pcm_volume(stream, left, right);
5126 else
5127 out->apply_volume = true;
5128
5129 out->volume_l = left;
5130 out->volume_r = right;
5131 return ret;
Derek Chenf13dd492018-11-13 14:53:51 -08005132 } else if (audio_extn_auto_hal_is_bus_device_usecase(out->usecase)) {
5133 ALOGV("%s: bus device set volume called", __func__);
5134 if (!out->standby)
5135 ret = out_set_pcm_volume(stream, left, right);
5136 out->volume_l = left;
5137 out->volume_r = right;
5138 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07005139 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005140
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005141 return -ENOSYS;
5142}
5143
Zhou Songc9672822017-08-16 16:01:39 +08005144static void update_frames_written(struct stream_out *out, size_t bytes)
5145{
5146 size_t bpf = 0;
5147
5148 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5149 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5150 bpf = 1;
5151 else if (!is_offload_usecase(out->usecase))
5152 bpf = audio_bytes_per_sample(out->format) *
5153 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005154
5155 pthread_mutex_lock(&out->position_query_lock);
5156 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005157 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005158 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5159 }
5160 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005161}
5162
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005163int split_and_write_audio_haptic_data(struct stream_out *out,
5164 const void *buffer, size_t bytes_to_write)
5165{
5166 struct audio_device *adev = out->dev;
5167
5168 int ret = 0;
5169 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5170 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5171 size_t frame_size = channel_count * bytes_per_sample;
5172 size_t frame_count = bytes_to_write / frame_size;
5173
5174 bool force_haptic_path =
5175 property_get_bool("vendor.audio.test_haptic", false);
5176
5177 // extract Haptics data from Audio buffer
5178 bool alloc_haptic_buffer = false;
5179 int haptic_channel_count = adev->haptics_config.channels;
5180 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5181 size_t audio_frame_size = frame_size - haptic_frame_size;
5182 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5183
5184 if (adev->haptic_buffer == NULL) {
5185 alloc_haptic_buffer = true;
5186 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5187 free(adev->haptic_buffer);
5188 adev->haptic_buffer_size = 0;
5189 alloc_haptic_buffer = true;
5190 }
5191
5192 if (alloc_haptic_buffer) {
5193 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005194 if(adev->haptic_buffer == NULL) {
5195 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5196 return -ENOMEM;
5197 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005198 adev->haptic_buffer_size = total_haptic_buffer_size;
5199 }
5200
5201 size_t src_index = 0, aud_index = 0, hap_index = 0;
5202 uint8_t *audio_buffer = (uint8_t *)buffer;
5203 uint8_t *haptic_buffer = adev->haptic_buffer;
5204
5205 // This is required for testing only. This works for stereo data only.
5206 // One channel is fed to audio stream and other to haptic stream for testing.
5207 if (force_haptic_path)
5208 audio_frame_size = haptic_frame_size = bytes_per_sample;
5209
5210 for (size_t i = 0; i < frame_count; i++) {
5211 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5212 audio_frame_size);
5213 aud_index += audio_frame_size;
5214 src_index += audio_frame_size;
5215
5216 if (adev->haptic_pcm)
5217 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5218 haptic_frame_size);
5219 hap_index += haptic_frame_size;
5220 src_index += haptic_frame_size;
5221
5222 // This is required for testing only.
5223 // Discard haptic channel data.
5224 if (force_haptic_path)
5225 src_index += haptic_frame_size;
5226 }
5227
5228 // write to audio pipeline
5229 ret = pcm_write(out->pcm, (void *)audio_buffer,
5230 frame_count * audio_frame_size);
5231
5232 // write to haptics pipeline
5233 if (adev->haptic_pcm)
5234 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5235 frame_count * haptic_frame_size);
5236
5237 return ret;
5238}
5239
Aalique Grahame22e49102018-12-18 14:23:57 -08005240#ifdef NO_AUDIO_OUT
5241static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5242 const void *buffer __unused, size_t bytes)
5243{
5244 struct stream_out *out = (struct stream_out *)stream;
5245
5246 /* No Output device supported other than BT for playback.
5247 * Sleep for the amount of buffer duration
5248 */
5249 lock_output_stream(out);
5250 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5251 (const struct audio_stream_out *)&out->stream) /
5252 out_get_sample_rate(&out->stream.common));
5253 pthread_mutex_unlock(&out->lock);
5254 return bytes;
5255}
5256#endif
5257
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005258static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5259 size_t bytes)
5260{
5261 struct stream_out *out = (struct stream_out *)stream;
5262 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005263 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305264 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005265 const size_t frame_size = audio_stream_out_frame_size(stream);
5266 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305267 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005268
Haynes Mathew George380745d2017-10-04 15:27:45 -07005269 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005270 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305271
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305272 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005273
Dhananjay Kumarac341582017-02-23 23:42:25 +05305274 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305275 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305276 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5277 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005278 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305279 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305280 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305281 ALOGD(" %s: sound card is not active/SSR state", __func__);
5282 ret= -EIO;
5283 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305284 }
5285 }
5286
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305287 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305288 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305289 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305290 goto exit;
5291 }
5292
Haynes Mathew George16081042017-05-31 17:16:49 -07005293 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5294 ret = -EINVAL;
5295 goto exit;
5296 }
5297
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305298 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5299 !out->is_iec61937_info_available) {
5300
5301 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5302 out->is_iec61937_info_available = true;
5303 } else if (audio_extn_passthru_is_enabled()) {
5304 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305305 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305306
5307 if((out->format == AUDIO_FORMAT_DTS) ||
5308 (out->format == AUDIO_FORMAT_DTS_HD)) {
5309 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5310 buffer, bytes);
5311 if (ret) {
5312 if (ret != -ENOSYS) {
5313 out->is_iec61937_info_available = false;
5314 ALOGD("iec61937 transmission info not yet updated retry");
5315 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305316 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305317 /* if stream has started and after that there is
5318 * stream config change (iec transmission config)
5319 * then trigger select_device to update backend configuration.
5320 */
5321 out->stream_config_changed = true;
5322 pthread_mutex_lock(&adev->lock);
5323 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305324 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005325 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305326 ret = -EINVAL;
5327 goto exit;
5328 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305329 pthread_mutex_unlock(&adev->lock);
5330 out->stream_config_changed = false;
5331 out->is_iec61937_info_available = true;
5332 }
5333 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305334
Garmond Leung317cbf12017-09-13 16:20:50 -07005335 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305336 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5337 (out->is_iec61937_info_available == true)) {
5338 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5339 ret = -EINVAL;
5340 goto exit;
5341 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305342 }
5343 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305344
5345 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005346 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005347 if (!(out->devices &
5348 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305349 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305350 ret = -EIO;
5351 goto exit;
5352 }
5353 }
5354 }
5355
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005356 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005357 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005358 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005359 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5360 ret = voice_extn_compress_voip_start_output_stream(out);
5361 else
5362 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005363 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005364 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005365 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005366 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005367 goto exit;
5368 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305369 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005370 if (last_known_cal_step != -1) {
5371 ALOGD("%s: retry previous failed cal level set", __func__);
5372 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305373 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005374 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305375
5376 if ((out->is_iec61937_info_available == true) &&
5377 (audio_extn_passthru_is_passthrough_stream(out))&&
5378 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5379 ret = -EINVAL;
5380 goto exit;
5381 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305382 if (out->set_dual_mono)
5383 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005384 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005385
Ashish Jain81eb2a82015-05-13 10:52:34 +05305386 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005387 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305388 adev->is_channel_status_set = true;
5389 }
5390
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305391 if ((adev->use_old_pspd_mix_ctrl == true) &&
5392 (out->pspd_coeff_sent == false)) {
5393 /*
5394 * Need to resend pspd coefficients after stream started for
5395 * older kernel version as it does not save the coefficients
5396 * and also stream has to be started for coeff to apply.
5397 */
5398 usecase = get_usecase_from_list(adev, out->usecase);
5399 if (usecase != NULL) {
5400 audio_extn_set_custom_mtmx_params(adev, usecase, true);
5401 out->pspd_coeff_sent = true;
5402 }
5403 }
5404
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005405 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005406 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005407 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005408 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005409 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5410 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305411 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5412 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005413 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305414 out->send_next_track_params = false;
5415 out->is_compr_metadata_avail = false;
5416 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005417 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305418 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305419 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005420
Ashish Jain83a6cc22016-06-28 14:34:17 +05305421 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305422 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305423 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305424 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005425 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305426 return -EINVAL;
5427 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305428 audio_format_t dst_format = out->hal_op_format;
5429 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305430
Dieter Luecking5d57def2018-09-07 14:23:37 +02005431 /* prevent division-by-zero */
5432 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5433 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5434 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5435 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305436 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005437 ATRACE_END();
5438 return -EINVAL;
5439 }
5440
Ashish Jainf1eaa582016-05-23 20:54:24 +05305441 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5442 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5443
Ashish Jain83a6cc22016-06-28 14:34:17 +05305444 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305445 dst_format,
5446 buffer,
5447 src_format,
5448 frames);
5449
Ashish Jain83a6cc22016-06-28 14:34:17 +05305450 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305451 bytes_to_write);
5452
5453 /*Convert written bytes in audio flinger format*/
5454 if (ret > 0)
5455 ret = ((ret * format_to_bitwidth_table[out->format]) /
5456 format_to_bitwidth_table[dst_format]);
5457 }
5458 } else
5459 ret = compress_write(out->compr, buffer, bytes);
5460
Zhou Songc9672822017-08-16 16:01:39 +08005461 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5462 update_frames_written(out, bytes);
5463
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305464 if (ret < 0)
5465 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005466 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305467 /*msg to cb thread only if non blocking write is enabled*/
5468 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305469 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005470 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305471 } else if (-ENETRESET == ret) {
5472 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305473 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305474 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305475 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005476 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305477 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005478 }
Ashish Jain5106d362016-05-11 19:23:33 +05305479
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305480 /* Call compr start only when non-zero bytes of data is there to be rendered */
5481 if (!out->playback_started && ret > 0) {
5482 int status = compress_start(out->compr);
5483 if (status < 0) {
5484 ret = status;
5485 ALOGE("%s: compr start failed with err %d", __func__, errno);
5486 goto exit;
5487 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005488 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005489 out->playback_started = 1;
5490 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005491
5492 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5493 popcount(out->channel_mask),
5494 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005495 }
5496 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005497 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005498 return ret;
5499 } else {
5500 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005501 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005502 if (out->muted)
5503 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005504 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5505 __func__, frames, frame_size, bytes_to_write);
5506
Aalique Grahame22e49102018-12-18 14:23:57 -08005507 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005508 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5509 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5510 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005511 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5512 int16_t *src = (int16_t *)buffer;
5513 int16_t *dst = (int16_t *)buffer;
5514
5515 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5516 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005517 "out_write called for %s use case with wrong properties",
5518 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005519
5520 /*
5521 * FIXME: this can be removed once audio flinger mixer supports
5522 * mono output
5523 */
5524
5525 /*
5526 * Code below goes over each frame in the buffer and adds both
5527 * L and R samples and then divides by 2 to convert to mono
5528 */
5529 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5530 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5531 }
5532 bytes_to_write /= 2;
5533 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005534
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305535 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005536
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005537 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005538
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005539 if (out->config.rate)
5540 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5541 out->config.rate;
5542
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005543 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005544 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5545
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005546 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005547 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005548 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305549 out->convert_buffer != NULL) {
5550
5551 memcpy_by_audio_format(out->convert_buffer,
5552 out->hal_op_format,
5553 buffer,
5554 out->hal_ip_format,
5555 out->config.period_size * out->config.channels);
5556
5557 ret = pcm_write(out->pcm, out->convert_buffer,
5558 (out->config.period_size *
5559 out->config.channels *
5560 format_to_bitwidth_table[out->hal_op_format]));
5561 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305562 /*
5563 * To avoid underrun in DSP when the application is not pumping
5564 * data at required rate, check for the no. of bytes and ignore
5565 * pcm_write if it is less than actual buffer size.
5566 * It is a work around to a change in compress VOIP driver.
5567 */
5568 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5569 bytes < (out->config.period_size * out->config.channels *
5570 audio_bytes_per_sample(out->format))) {
5571 size_t voip_buf_size =
5572 out->config.period_size * out->config.channels *
5573 audio_bytes_per_sample(out->format);
5574 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5575 __func__, bytes, voip_buf_size);
5576 usleep(((uint64_t)voip_buf_size - bytes) *
5577 1000000 / audio_stream_out_frame_size(stream) /
5578 out_get_sample_rate(&out->stream.common));
5579 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005580 } else {
5581 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5582 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5583 else
5584 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5585 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305586 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005587
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005588 release_out_focus(out);
5589
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305590 if (ret < 0)
5591 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005592 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305593 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005594 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005595 }
5596
5597exit:
Zhou Songc9672822017-08-16 16:01:39 +08005598 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305599 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305600 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305601 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005602 pthread_mutex_unlock(&out->lock);
5603
5604 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005605 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005606 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305607 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305608 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305609 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305610 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305611 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305612 out->standby = true;
5613 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305614 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005615 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5616 /* prevent division-by-zero */
5617 uint32_t stream_size = audio_stream_out_frame_size(stream);
5618 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005619
Dieter Luecking5d57def2018-09-07 14:23:37 +02005620 if ((stream_size == 0) || (srate == 0)) {
5621 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5622 ATRACE_END();
5623 return -EINVAL;
5624 }
5625 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5626 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005627 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305628 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005629 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005630 return ret;
5631 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005632 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005633 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005634 return bytes;
5635}
5636
5637static int out_get_render_position(const struct audio_stream_out *stream,
5638 uint32_t *dsp_frames)
5639{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005640 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005641
5642 if (dsp_frames == NULL)
5643 return -EINVAL;
5644
5645 *dsp_frames = 0;
5646 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005647 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305648
5649 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5650 * this operation and adev_close_output_stream(where out gets reset).
5651 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305652 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005653 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305654 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005655 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305656 return 0;
5657 }
5658
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005659 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305660 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305661 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005662 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305663 if (ret < 0)
5664 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005665 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305666 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005667 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305668 if (-ENETRESET == ret) {
5669 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305670 out->card_status = CARD_STATUS_OFFLINE;
5671 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305672 } else if(ret < 0) {
5673 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305674 ret = -EINVAL;
5675 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305676 /*
5677 * Handle corner case where compress session is closed during SSR
5678 * and timestamp is queried
5679 */
5680 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305681 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305682 } else if (out->prev_card_status_offline) {
5683 ALOGE("ERROR: previously sound card was offline,return error");
5684 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305685 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305686 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005687 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305688 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305689 pthread_mutex_unlock(&out->lock);
5690 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005691 } else if (audio_is_linear_pcm(out->format)) {
5692 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005693 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005694 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005695 } else
5696 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005697}
5698
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005699static int out_add_audio_effect(const struct audio_stream *stream __unused,
5700 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005701{
5702 return 0;
5703}
5704
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005705static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5706 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005707{
5708 return 0;
5709}
5710
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005711static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5712 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005713{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305714 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005715}
5716
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005717static int out_get_presentation_position(const struct audio_stream_out *stream,
5718 uint64_t *frames, struct timespec *timestamp)
5719{
5720 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305721 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005722 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005723
Ashish Jain5106d362016-05-11 19:23:33 +05305724 /* below piece of code is not guarded against any lock because audioFliner serializes
5725 * this operation and adev_close_output_stream( where out gets reset).
5726 */
5727 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305728 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005729 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305730 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5731 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5732 return 0;
5733 }
5734
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005735 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005736
Ashish Jain5106d362016-05-11 19:23:33 +05305737 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5738 ret = compress_get_tstamp(out->compr, &dsp_frames,
5739 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005740 // Adjustment accounts for A2dp encoder latency with offload usecases
5741 // Note: Encoder latency is returned in ms.
5742 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5743 unsigned long offset =
5744 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5745 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5746 }
Ashish Jain5106d362016-05-11 19:23:33 +05305747 ALOGVV("%s rendered frames %ld sample_rate %d",
5748 __func__, dsp_frames, out->sample_rate);
5749 *frames = dsp_frames;
5750 if (ret < 0)
5751 ret = -errno;
5752 if (-ENETRESET == ret) {
5753 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305754 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305755 ret = -EINVAL;
5756 } else
5757 ret = 0;
5758 /* this is the best we can do */
5759 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005760 } else {
5761 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005762 unsigned int avail;
5763 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5764 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5765 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5766 // This adjustment accounts for buffering after app processor.
5767 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005768 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005769 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005770
Weiyin Jiangd4633762018-03-16 12:05:03 +08005771 // Adjustment accounts for A2dp encoder latency with non offload usecases
5772 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5773 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5774 signed_frames -=
5775 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5776 }
5777
5778 // It would be unusual for this value to be negative, but check just in case ...
5779 if (signed_frames >= 0) {
5780 *frames = signed_frames;
5781 ret = 0;
5782 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005783 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305784 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305785 *frames = out->written;
5786 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305787 if (is_offload_usecase(out->usecase))
5788 ret = -EINVAL;
5789 else
5790 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005791 }
5792 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005793 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005794 return ret;
5795}
5796
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005797static int out_set_callback(struct audio_stream_out *stream,
5798 stream_callback_t callback, void *cookie)
5799{
5800 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005801 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005802
5803 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005804 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005805 out->client_callback = callback;
5806 out->client_cookie = cookie;
5807 if (out->adsp_hdlr_stream_handle) {
5808 ret = audio_extn_adsp_hdlr_stream_set_callback(
5809 out->adsp_hdlr_stream_handle,
5810 callback,
5811 cookie);
5812 if (ret)
5813 ALOGW("%s:adsp hdlr callback registration failed %d",
5814 __func__, ret);
5815 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005816 pthread_mutex_unlock(&out->lock);
5817 return 0;
5818}
5819
5820static int out_pause(struct audio_stream_out* stream)
5821{
5822 struct stream_out *out = (struct stream_out *)stream;
5823 int status = -ENOSYS;
5824 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005825 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005826 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005827 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005828 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305829 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305830 status = compress_pause(out->compr);
5831
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005832 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005833
Mingming Yin21854652016-04-13 11:54:02 -07005834 if (audio_extn_passthru_is_active()) {
5835 ALOGV("offload use case, pause passthru");
5836 audio_extn_passthru_on_pause(out);
5837 }
5838
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305839 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005840 audio_extn_dts_notify_playback_state(out->usecase, 0,
5841 out->sample_rate, popcount(out->channel_mask),
5842 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005843 }
5844 pthread_mutex_unlock(&out->lock);
5845 }
5846 return status;
5847}
5848
5849static int out_resume(struct audio_stream_out* stream)
5850{
5851 struct stream_out *out = (struct stream_out *)stream;
5852 int status = -ENOSYS;
5853 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005854 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005855 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005856 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005857 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005858 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305859 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305860 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005861 }
5862 if (!status) {
5863 out->offload_state = OFFLOAD_STATE_PLAYING;
5864 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305865 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005866 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5867 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005868 }
5869 pthread_mutex_unlock(&out->lock);
5870 }
5871 return status;
5872}
5873
5874static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5875{
5876 struct stream_out *out = (struct stream_out *)stream;
5877 int status = -ENOSYS;
5878 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005879 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005880 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005881 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5882 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5883 else
5884 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5885 pthread_mutex_unlock(&out->lock);
5886 }
5887 return status;
5888}
5889
5890static int out_flush(struct audio_stream_out* stream)
5891{
5892 struct stream_out *out = (struct stream_out *)stream;
5893 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005894 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005895 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005896 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005897 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5898 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005899 } else {
5900 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5901 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005902 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005903 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005904 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005905 return 0;
5906 }
5907 return -ENOSYS;
5908}
5909
Haynes Mathew George16081042017-05-31 17:16:49 -07005910static int out_stop(const struct audio_stream_out* stream)
5911{
5912 struct stream_out *out = (struct stream_out *)stream;
5913 struct audio_device *adev = out->dev;
5914 int ret = -ENOSYS;
5915
5916 ALOGV("%s", __func__);
5917 pthread_mutex_lock(&adev->lock);
5918 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5919 out->playback_started && out->pcm != NULL) {
5920 pcm_stop(out->pcm);
5921 ret = stop_output_stream(out);
5922 out->playback_started = false;
5923 }
5924 pthread_mutex_unlock(&adev->lock);
5925 return ret;
5926}
5927
5928static int out_start(const struct audio_stream_out* stream)
5929{
5930 struct stream_out *out = (struct stream_out *)stream;
5931 struct audio_device *adev = out->dev;
5932 int ret = -ENOSYS;
5933
5934 ALOGV("%s", __func__);
5935 pthread_mutex_lock(&adev->lock);
5936 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5937 !out->playback_started && out->pcm != NULL) {
5938 ret = start_output_stream(out);
5939 if (ret == 0) {
5940 out->playback_started = true;
5941 }
5942 }
5943 pthread_mutex_unlock(&adev->lock);
5944 return ret;
5945}
5946
5947/*
5948 * Modify config->period_count based on min_size_frames
5949 */
5950static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5951{
5952 int periodCountRequested = (min_size_frames + config->period_size - 1)
5953 / config->period_size;
5954 int periodCount = MMAP_PERIOD_COUNT_MIN;
5955
5956 ALOGV("%s original config.period_size = %d config.period_count = %d",
5957 __func__, config->period_size, config->period_count);
5958
5959 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5960 periodCount *= 2;
5961 }
5962 config->period_count = periodCount;
5963
5964 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5965}
5966
Phil Burkfe17efd2019-03-25 10:23:35 -07005967// Read offset for the positional timestamp from a persistent vendor property.
5968// This is to workaround apparent inaccuracies in the timing information that
5969// is used by the AAudio timing model. The inaccuracies can cause glitches.
5970static int64_t get_mmap_out_time_offset() {
5971 const int32_t kDefaultOffsetMicros = 0;
5972 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08005973 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07005974 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
5975 return mmap_time_offset_micros * (int64_t)1000;
5976}
5977
Haynes Mathew George16081042017-05-31 17:16:49 -07005978static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5979 int32_t min_size_frames,
5980 struct audio_mmap_buffer_info *info)
5981{
5982 struct stream_out *out = (struct stream_out *)stream;
5983 struct audio_device *adev = out->dev;
5984 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005985 unsigned int offset1 = 0;
5986 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005987 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005988 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005989 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005990
Arun Mirpuri5d170872019-03-26 13:21:31 -07005991 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305992 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005993 pthread_mutex_lock(&adev->lock);
5994
Sharad Sanglec6f32552018-05-04 16:15:38 +05305995 if (CARD_STATUS_OFFLINE == out->card_status ||
5996 CARD_STATUS_OFFLINE == adev->card_status) {
5997 ALOGW("out->card_status or adev->card_status offline, try again");
5998 ret = -EIO;
5999 goto exit;
6000 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006001 if (info == NULL || min_size_frames == 0) {
6002 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
6003 ret = -EINVAL;
6004 goto exit;
6005 }
6006 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
6007 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
6008 ret = -ENOSYS;
6009 goto exit;
6010 }
6011 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
6012 if (out->pcm_device_id < 0) {
6013 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6014 __func__, out->pcm_device_id, out->usecase);
6015 ret = -EINVAL;
6016 goto exit;
6017 }
6018
6019 adjust_mmap_period_count(&out->config, min_size_frames);
6020
Arun Mirpuri5d170872019-03-26 13:21:31 -07006021 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006022 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
6023 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
6024 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306025 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306026 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6027 out->card_status = CARD_STATUS_OFFLINE;
6028 adev->card_status = CARD_STATUS_OFFLINE;
6029 ret = -EIO;
6030 goto exit;
6031 }
6032
Haynes Mathew George16081042017-05-31 17:16:49 -07006033 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
6034 step = "open";
6035 ret = -ENODEV;
6036 goto exit;
6037 }
6038 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
6039 if (ret < 0) {
6040 step = "begin";
6041 goto exit;
6042 }
6043 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07006044 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07006045 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006046 ret = platform_get_mmap_data_fd(adev->platform,
6047 out->pcm_device_id, 0 /*playback*/,
6048 &info->shared_memory_fd,
6049 &mmap_size);
6050 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07006051 // Fall back to non exclusive mode
6052 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
6053 } else {
6054 if (mmap_size < buffer_size) {
6055 step = "mmap";
6056 goto exit;
6057 }
6058 // FIXME: indicate exclusive mode support by returning a negative buffer size
6059 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006060 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006061 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07006062 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07006063
6064 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
6065 if (ret < 0) {
6066 step = "commit";
6067 goto exit;
6068 }
6069
Phil Burkfe17efd2019-03-25 10:23:35 -07006070 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
6071
Haynes Mathew George16081042017-05-31 17:16:49 -07006072 out->standby = false;
6073 ret = 0;
6074
Arun Mirpuri5d170872019-03-26 13:21:31 -07006075 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07006076 __func__, info->shared_memory_address, info->buffer_size_frames);
6077
6078exit:
6079 if (ret != 0) {
6080 if (out->pcm == NULL) {
6081 ALOGE("%s: %s - %d", __func__, step, ret);
6082 } else {
6083 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
6084 pcm_close(out->pcm);
6085 out->pcm = NULL;
6086 }
6087 }
6088 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05306089 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07006090 return ret;
6091}
6092
6093static int out_get_mmap_position(const struct audio_stream_out *stream,
6094 struct audio_mmap_position *position)
6095{
6096 struct stream_out *out = (struct stream_out *)stream;
6097 ALOGVV("%s", __func__);
6098 if (position == NULL) {
6099 return -EINVAL;
6100 }
6101 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08006102 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006103 return -ENOSYS;
6104 }
6105 if (out->pcm == NULL) {
6106 return -ENOSYS;
6107 }
6108
6109 struct timespec ts = { 0, 0 };
6110 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
6111 if (ret < 0) {
6112 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
6113 return ret;
6114 }
Phil Burkfe17efd2019-03-25 10:23:35 -07006115 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6116 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006117 return 0;
6118}
6119
6120
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006121/** audio_stream_in implementation **/
6122static uint32_t in_get_sample_rate(const struct audio_stream *stream)
6123{
6124 struct stream_in *in = (struct stream_in *)stream;
6125
6126 return in->config.rate;
6127}
6128
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006129static int in_set_sample_rate(struct audio_stream *stream __unused,
6130 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006131{
6132 return -ENOSYS;
6133}
6134
6135static size_t in_get_buffer_size(const struct audio_stream *stream)
6136{
6137 struct stream_in *in = (struct stream_in *)stream;
6138
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006139 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
6140 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006141 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
6142 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 -07006143 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6144 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306145 else if(audio_extn_cin_attached_usecase(in->usecase))
6146 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006147
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006148 return in->config.period_size * in->af_period_multiplier *
6149 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006150}
6151
6152static uint32_t in_get_channels(const struct audio_stream *stream)
6153{
6154 struct stream_in *in = (struct stream_in *)stream;
6155
6156 return in->channel_mask;
6157}
6158
6159static audio_format_t in_get_format(const struct audio_stream *stream)
6160{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006161 struct stream_in *in = (struct stream_in *)stream;
6162
6163 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006164}
6165
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006166static int in_set_format(struct audio_stream *stream __unused,
6167 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006168{
6169 return -ENOSYS;
6170}
6171
6172static int in_standby(struct audio_stream *stream)
6173{
6174 struct stream_in *in = (struct stream_in *)stream;
6175 struct audio_device *adev = in->dev;
6176 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306177 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6178 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006179 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306180
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006181 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006182 if (!in->standby && in->is_st_session) {
6183 ALOGD("%s: sound trigger pcm stop lab", __func__);
6184 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006185 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006186 in->standby = 1;
6187 }
6188
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006189 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006190 if (adev->adm_deregister_stream)
6191 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6192
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006193 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006194 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006195 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006196 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006197 voice_extn_compress_voip_close_input_stream(stream);
6198 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006199 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6200 do_stop = in->capture_started;
6201 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006202 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306203 if (audio_extn_cin_attached_usecase(in->usecase))
6204 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006205 }
6206
Arun Mirpuri5d170872019-03-26 13:21:31 -07006207 if (in->pcm) {
6208 ATRACE_BEGIN("pcm_in_close");
6209 pcm_close(in->pcm);
6210 ATRACE_END();
6211 in->pcm = NULL;
6212 }
6213
Carter Hsu2e429db2019-05-14 18:50:52 +08006214 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
Aalique Grahame22e49102018-12-18 14:23:57 -08006215 adev->enable_voicerx = false;
Carter Hsu2e429db2019-05-14 18:50:52 +08006216
6217 if (do_stop)
Zhou Songa8895042016-07-05 17:54:22 +08006218 status = stop_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006219
6220 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6221 adev->num_va_sessions--;
6222
Eric Laurent150dbfe2013-02-27 14:31:02 -08006223 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006224 }
6225 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006226 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006227 return status;
6228}
6229
Aalique Grahame22e49102018-12-18 14:23:57 -08006230static int in_dump(const struct audio_stream *stream,
6231 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006232{
Aalique Grahame22e49102018-12-18 14:23:57 -08006233 struct stream_in *in = (struct stream_in *)stream;
6234
6235 // We try to get the lock for consistency,
6236 // but it isn't necessary for these variables.
6237 // If we're not in standby, we may be blocked on a read.
6238 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6239 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6240 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6241 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6242
6243 if (locked) {
6244 pthread_mutex_unlock(&in->lock);
6245 }
6246
6247 // dump error info
6248 (void)error_log_dump(
6249 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6250
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006251 return 0;
6252}
6253
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306254static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6255{
6256 if (!stream || !parms)
6257 return;
6258
6259 struct stream_in *in = (struct stream_in *)stream;
6260 struct audio_device *adev = in->dev;
6261
6262 card_status_t status;
6263 int card;
6264 if (parse_snd_card_status(parms, &card, &status) < 0)
6265 return;
6266
6267 pthread_mutex_lock(&adev->lock);
6268 bool valid_cb = (card == adev->snd_card);
6269 pthread_mutex_unlock(&adev->lock);
6270
6271 if (!valid_cb)
6272 return;
6273
6274 lock_input_stream(in);
6275 if (in->card_status != status)
6276 in->card_status = status;
6277 pthread_mutex_unlock(&in->lock);
6278
6279 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6280 use_case_table[in->usecase],
6281 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6282
6283 // a better solution would be to report error back to AF and let
6284 // it put the stream to standby
6285 if (status == CARD_STATUS_OFFLINE)
6286 in_standby(&in->stream.common);
6287
6288 return;
6289}
6290
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006291static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6292{
6293 struct stream_in *in = (struct stream_in *)stream;
6294 struct audio_device *adev = in->dev;
6295 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006296 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006297 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006298
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306299 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006300 parms = str_parms_create_str(kvpairs);
6301
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306302 if (!parms)
6303 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006304 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006305 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006306
6307 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6308 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006309 val = atoi(value);
6310 /* no audio source uses val == 0 */
6311 if ((in->source != val) && (val != 0)) {
6312 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006313 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6314 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6315 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006316 (in->config.rate == 8000 || in->config.rate == 16000 ||
6317 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006318 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006319 err = voice_extn_compress_voip_open_input_stream(in);
6320 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006321 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006322 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006323 }
6324 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006325 }
6326 }
6327
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006328 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6329 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006330 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006331 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6332
6333 // Workaround: If routing to an non existing usb device, fail gracefully
6334 // The routing request will otherwise block during 10 second
6335 int card;
6336 if (audio_is_usb_in_device(val) &&
6337 (card = get_alive_usb_card(parms)) >= 0) {
6338
6339 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6340 ret = -ENOSYS;
6341 } else {
6342
6343 in->device = val;
6344 /* If recording is in progress, change the tx device to new device */
6345 if (!in->standby && !in->is_st_session) {
6346 ALOGV("update input routing change");
6347 // inform adm before actual routing to prevent glitches.
6348 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006349 adev->adm_on_routing_change(adev->adm_data,
6350 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006351 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006352 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6353 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006354 }
6355 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006356 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006357 }
6358 }
6359
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306360 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6361 if (err >= 0) {
6362 strlcpy(in->profile, value, sizeof(in->profile));
6363 ALOGV("updating stream profile with value '%s'", in->profile);
6364 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6365 &adev->streams_input_cfg_list,
6366 in->device, in->flags, in->format,
6367 in->sample_rate, in->bit_width,
6368 in->profile, &in->app_type_cfg);
6369 }
6370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006371 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006372 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006373
6374 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306375error:
Eric Laurent994a6932013-07-17 11:51:42 -07006376 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006377 return ret;
6378}
6379
6380static char* in_get_parameters(const struct audio_stream *stream,
6381 const char *keys)
6382{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006383 struct stream_in *in = (struct stream_in *)stream;
6384 struct str_parms *query = str_parms_create_str(keys);
6385 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006386 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006387
6388 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006389 if (reply) {
6390 str_parms_destroy(reply);
6391 }
6392 if (query) {
6393 str_parms_destroy(query);
6394 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006395 ALOGE("in_get_parameters: failed to create query or reply");
6396 return NULL;
6397 }
6398
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006399 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006400
6401 voice_extn_in_get_parameters(in, query, reply);
6402
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006403 stream_get_parameter_channels(query, reply,
6404 &in->supported_channel_masks[0]);
6405 stream_get_parameter_formats(query, reply,
6406 &in->supported_formats[0]);
6407 stream_get_parameter_rates(query, reply,
6408 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006409 str = str_parms_to_str(reply);
6410 str_parms_destroy(query);
6411 str_parms_destroy(reply);
6412
6413 ALOGV("%s: exit: returns - %s", __func__, str);
6414 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006415}
6416
Aalique Grahame22e49102018-12-18 14:23:57 -08006417static int in_set_gain(struct audio_stream_in *stream,
6418 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006419{
Aalique Grahame22e49102018-12-18 14:23:57 -08006420 struct stream_in *in = (struct stream_in *)stream;
6421 char mixer_ctl_name[128];
6422 struct mixer_ctl *ctl;
6423 int ctl_value;
6424
6425 ALOGV("%s: gain %f", __func__, gain);
6426
6427 if (stream == NULL)
6428 return -EINVAL;
6429
6430 /* in_set_gain() only used to silence MMAP capture for now */
6431 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6432 return -ENOSYS;
6433
6434 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6435
6436 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6437 if (!ctl) {
6438 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6439 __func__, mixer_ctl_name);
6440 return -ENOSYS;
6441 }
6442
6443 if (gain < RECORD_GAIN_MIN)
6444 gain = RECORD_GAIN_MIN;
6445 else if (gain > RECORD_GAIN_MAX)
6446 gain = RECORD_GAIN_MAX;
6447 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6448
6449 mixer_ctl_set_value(ctl, 0, ctl_value);
6450
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006451 return 0;
6452}
6453
6454static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6455 size_t bytes)
6456{
6457 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306458
6459 if (in == NULL) {
6460 ALOGE("%s: stream_in ptr is NULL", __func__);
6461 return -EINVAL;
6462 }
6463
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006464 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306465 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306466 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006467
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006468 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306469
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006470 if (in->is_st_session) {
6471 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6472 /* Read from sound trigger HAL */
6473 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006474 if (in->standby) {
6475 adev->num_va_sessions++;
6476 in->standby = 0;
6477 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006478 pthread_mutex_unlock(&in->lock);
6479 return bytes;
6480 }
6481
Haynes Mathew George16081042017-05-31 17:16:49 -07006482 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6483 ret = -ENOSYS;
6484 goto exit;
6485 }
6486
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006487 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6488 !in->standby && adev->adm_routing_changed) {
6489 ret = -ENOSYS;
6490 goto exit;
6491 }
6492
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006493 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006494 pthread_mutex_lock(&adev->lock);
6495 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6496 ret = voice_extn_compress_voip_start_input_stream(in);
6497 else
6498 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006499 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6500 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006501 pthread_mutex_unlock(&adev->lock);
6502 if (ret != 0) {
6503 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006504 }
6505 in->standby = 0;
6506 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006507
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006508 // what's the duration requested by the client?
6509 long ns = 0;
6510
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306511 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006512 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6513 in->config.rate;
6514
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006515 ret = request_in_focus(in, ns);
6516 if (ret != 0)
6517 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006518 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006519
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306520 if (audio_extn_cin_attached_usecase(in->usecase)) {
6521 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6522 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306523 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006524 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306525 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006526 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006527 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006528 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006529 } else if (audio_extn_ffv_get_stream() == in) {
6530 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306531 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006532 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306533 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6534 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6535 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6536 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306537 ret = -EINVAL;
6538 goto exit;
6539 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306540 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306541 ret = -errno;
6542 }
6543 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306544 /* bytes read is always set to bytes for non compress usecases */
6545 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006546 }
6547
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006548 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006549
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006550 /*
Quinn Malef6050362019-01-30 15:55:40 -08006551 * Instead of writing zeroes here, we could trust the hardware to always
6552 * provide zeroes when muted. This is also muted with voice recognition
6553 * usecases so that other clients do not have access to voice recognition
6554 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006555 */
Quinn Malef6050362019-01-30 15:55:40 -08006556 if ((ret == 0 && voice_get_mic_mute(adev) &&
6557 !voice_is_in_call_rec_stream(in) &&
6558 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6559 (adev->num_va_sessions &&
6560 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6561 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6562 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006563 memset(buffer, 0, bytes);
6564
6565exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306566 frame_size = audio_stream_in_frame_size(stream);
6567 if (frame_size > 0)
6568 in->frames_read += bytes_read/frame_size;
6569
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006570 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306571 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006572 pthread_mutex_unlock(&in->lock);
6573
6574 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306575 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306576 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306577 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306578 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306579 in->standby = true;
6580 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306581 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6582 bytes_read = bytes;
6583 memset(buffer, 0, bytes);
6584 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006585 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006586 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6587 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006588 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306589 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306590 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006591 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306592 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006593}
6594
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006595static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006596{
6597 return 0;
6598}
6599
Aalique Grahame22e49102018-12-18 14:23:57 -08006600static int in_get_capture_position(const struct audio_stream_in *stream,
6601 int64_t *frames, int64_t *time)
6602{
6603 if (stream == NULL || frames == NULL || time == NULL) {
6604 return -EINVAL;
6605 }
6606 struct stream_in *in = (struct stream_in *)stream;
6607 int ret = -ENOSYS;
6608
6609 lock_input_stream(in);
6610 // note: ST sessions do not close the alsa pcm driver synchronously
6611 // on standby. Therefore, we may return an error even though the
6612 // pcm stream is still opened.
6613 if (in->standby) {
6614 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6615 "%s stream in standby but pcm not NULL for non ST session", __func__);
6616 goto exit;
6617 }
6618 if (in->pcm) {
6619 struct timespec timestamp;
6620 unsigned int avail;
6621 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6622 *frames = in->frames_read + avail;
6623 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6624 ret = 0;
6625 }
6626 }
6627exit:
6628 pthread_mutex_unlock(&in->lock);
6629 return ret;
6630}
6631
Carter Hsu2e429db2019-05-14 18:50:52 +08006632static int in_update_effect_list(bool add, effect_handle_t effect,
6633 struct listnode *head)
6634{
6635 struct listnode *node;
6636 struct in_effect_list *elist = NULL;
6637 struct in_effect_list *target = NULL;
6638 int ret = 0;
6639
6640 if (!head)
6641 return ret;
6642
6643 list_for_each(node, head) {
6644 elist = node_to_item(node, struct in_effect_list, list);
6645 if (elist->handle == effect) {
6646 target = elist;
6647 break;
6648 }
6649 }
6650
6651 if (add) {
6652 if (target) {
6653 ALOGD("effect %p already exist", effect);
6654 return ret;
6655 }
6656
6657 target = (struct in_effect_list *)
6658 calloc(1, sizeof(struct in_effect_list));
6659
6660 if (!target) {
6661 ALOGE("%s:fail to allocate memory", __func__);
6662 return -ENOMEM;
6663 }
6664
6665 target->handle = effect;
6666 list_add_tail(head, &target->list);
6667 } else {
6668 if (target) {
6669 list_remove(&target->list);
6670 free(target);
6671 }
6672 }
6673
6674 return ret;
6675}
6676
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006677static int add_remove_audio_effect(const struct audio_stream *stream,
6678 effect_handle_t effect,
6679 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006680{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006681 struct stream_in *in = (struct stream_in *)stream;
6682 int status = 0;
6683 effect_descriptor_t desc;
6684
6685 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006686 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6687
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006688 if (status != 0)
6689 return status;
6690
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006691 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006692 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006693 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Carter Hsu2e429db2019-05-14 18:50:52 +08006694 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
6695 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006696 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
Carter Hsu2e429db2019-05-14 18:50:52 +08006697
6698 in_update_effect_list(enable, effect, &in->aec_list);
6699 enable = !list_empty(&in->aec_list);
6700 if (enable == in->enable_aec)
6701 goto exit;
6702
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006703 in->enable_aec = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006704 ALOGD("AEC enable %d", enable);
6705
Aalique Grahame22e49102018-12-18 14:23:57 -08006706 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6707 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6708 in->dev->enable_voicerx = enable;
6709 struct audio_usecase *usecase;
6710 struct listnode *node;
6711 list_for_each(node, &in->dev->usecase_list) {
6712 usecase = node_to_item(node, struct audio_usecase, list);
6713 if (usecase->type == PCM_PLAYBACK)
6714 select_devices(in->dev, usecase->id);
6715 }
6716 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006717 if (!in->standby) {
6718 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6719 select_devices(in->dev, in->usecase);
6720 }
6721
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006722 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006723 if (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0) {
6724
6725 in_update_effect_list(enable, effect, &in->ns_list);
6726 enable = !list_empty(&in->ns_list);
6727 if (enable == in->enable_ns)
6728 goto exit;
6729
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006730 in->enable_ns = enable;
Carter Hsu2e429db2019-05-14 18:50:52 +08006731 ALOGD("NS enable %d", enable);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006732 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006733 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6734 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006735 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6736 select_devices(in->dev, in->usecase);
6737 } else
6738 select_devices(in->dev, in->usecase);
6739 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006740 }
Carter Hsu2e429db2019-05-14 18:50:52 +08006741exit:
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006742 pthread_mutex_unlock(&in->dev->lock);
6743 pthread_mutex_unlock(&in->lock);
6744
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006745 return 0;
6746}
6747
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006748static int in_add_audio_effect(const struct audio_stream *stream,
6749 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006750{
Eric Laurent994a6932013-07-17 11:51:42 -07006751 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006752 return add_remove_audio_effect(stream, effect, true);
6753}
6754
6755static int in_remove_audio_effect(const struct audio_stream *stream,
6756 effect_handle_t effect)
6757{
Eric Laurent994a6932013-07-17 11:51:42 -07006758 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006759 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006760}
6761
Derek Chenf939fb72018-11-13 13:34:41 -08006762streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6763 audio_io_handle_t input)
6764{
6765 struct listnode *node;
6766
6767 list_for_each(node, &dev->active_inputs_list) {
6768 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6769 streams_input_ctxt_t,
6770 list);
6771 if (in_ctxt->input->capture_handle == input) {
6772 return in_ctxt;
6773 }
6774 }
6775 return NULL;
6776}
6777
6778streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6779 audio_io_handle_t output)
6780{
6781 struct listnode *node;
6782
6783 list_for_each(node, &dev->active_outputs_list) {
6784 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6785 streams_output_ctxt_t,
6786 list);
6787 if (out_ctxt->output->handle == output) {
6788 return out_ctxt;
6789 }
6790 }
6791 return NULL;
6792}
6793
Haynes Mathew George16081042017-05-31 17:16:49 -07006794static int in_stop(const struct audio_stream_in* stream)
6795{
6796 struct stream_in *in = (struct stream_in *)stream;
6797 struct audio_device *adev = in->dev;
6798
6799 int ret = -ENOSYS;
6800 ALOGV("%s", __func__);
6801 pthread_mutex_lock(&adev->lock);
6802 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6803 in->capture_started && in->pcm != NULL) {
6804 pcm_stop(in->pcm);
6805 ret = stop_input_stream(in);
6806 in->capture_started = false;
6807 }
6808 pthread_mutex_unlock(&adev->lock);
6809 return ret;
6810}
6811
6812static int in_start(const struct audio_stream_in* stream)
6813{
6814 struct stream_in *in = (struct stream_in *)stream;
6815 struct audio_device *adev = in->dev;
6816 int ret = -ENOSYS;
6817
6818 ALOGV("%s in %p", __func__, in);
6819 pthread_mutex_lock(&adev->lock);
6820 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6821 !in->capture_started && in->pcm != NULL) {
6822 if (!in->capture_started) {
6823 ret = start_input_stream(in);
6824 if (ret == 0) {
6825 in->capture_started = true;
6826 }
6827 }
6828 }
6829 pthread_mutex_unlock(&adev->lock);
6830 return ret;
6831}
6832
Phil Burke0a86d12019-02-16 22:28:11 -08006833// Read offset for the positional timestamp from a persistent vendor property.
6834// This is to workaround apparent inaccuracies in the timing information that
6835// is used by the AAudio timing model. The inaccuracies can cause glitches.
6836static int64_t in_get_mmap_time_offset() {
6837 const int32_t kDefaultOffsetMicros = 0;
6838 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006839 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006840 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6841 return mmap_time_offset_micros * (int64_t)1000;
6842}
6843
Haynes Mathew George16081042017-05-31 17:16:49 -07006844static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6845 int32_t min_size_frames,
6846 struct audio_mmap_buffer_info *info)
6847{
6848 struct stream_in *in = (struct stream_in *)stream;
6849 struct audio_device *adev = in->dev;
6850 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006851 unsigned int offset1 = 0;
6852 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006853 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006854 uint32_t mmap_size = 0;
6855 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006856
6857 pthread_mutex_lock(&adev->lock);
6858 ALOGV("%s in %p", __func__, in);
6859
Sharad Sanglec6f32552018-05-04 16:15:38 +05306860 if (CARD_STATUS_OFFLINE == in->card_status||
6861 CARD_STATUS_OFFLINE == adev->card_status) {
6862 ALOGW("in->card_status or adev->card_status offline, try again");
6863 ret = -EIO;
6864 goto exit;
6865 }
6866
Haynes Mathew George16081042017-05-31 17:16:49 -07006867 if (info == NULL || min_size_frames == 0) {
6868 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6869 ret = -EINVAL;
6870 goto exit;
6871 }
6872 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6873 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6874 ALOGV("%s in %p", __func__, in);
6875 ret = -ENOSYS;
6876 goto exit;
6877 }
6878 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6879 if (in->pcm_device_id < 0) {
6880 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6881 __func__, in->pcm_device_id, in->usecase);
6882 ret = -EINVAL;
6883 goto exit;
6884 }
6885
6886 adjust_mmap_period_count(&in->config, min_size_frames);
6887
6888 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6889 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6890 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6891 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306892 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306893 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6894 in->card_status = CARD_STATUS_OFFLINE;
6895 adev->card_status = CARD_STATUS_OFFLINE;
6896 ret = -EIO;
6897 goto exit;
6898 }
6899
Haynes Mathew George16081042017-05-31 17:16:49 -07006900 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6901 step = "open";
6902 ret = -ENODEV;
6903 goto exit;
6904 }
6905
6906 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6907 if (ret < 0) {
6908 step = "begin";
6909 goto exit;
6910 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006911
Arun Mirpuri5d170872019-03-26 13:21:31 -07006912 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6913 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6914 info->burst_size_frames = in->config.period_size;
6915 ret = platform_get_mmap_data_fd(adev->platform,
6916 in->pcm_device_id, 1 /*capture*/,
6917 &info->shared_memory_fd,
6918 &mmap_size);
6919 if (ret < 0) {
6920 // Fall back to non exclusive mode
6921 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6922 } else {
6923 if (mmap_size < buffer_size) {
6924 step = "mmap";
6925 goto exit;
6926 }
6927 // FIXME: indicate exclusive mode support by returning a negative buffer size
6928 info->buffer_size_frames *= -1;
6929 }
6930
6931 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006932
6933 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6934 if (ret < 0) {
6935 step = "commit";
6936 goto exit;
6937 }
6938
Phil Burke0a86d12019-02-16 22:28:11 -08006939 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
6940
Haynes Mathew George16081042017-05-31 17:16:49 -07006941 in->standby = false;
6942 ret = 0;
6943
6944 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6945 __func__, info->shared_memory_address, info->buffer_size_frames);
6946
6947exit:
6948 if (ret != 0) {
6949 if (in->pcm == NULL) {
6950 ALOGE("%s: %s - %d", __func__, step, ret);
6951 } else {
6952 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6953 pcm_close(in->pcm);
6954 in->pcm = NULL;
6955 }
6956 }
6957 pthread_mutex_unlock(&adev->lock);
6958 return ret;
6959}
6960
6961static int in_get_mmap_position(const struct audio_stream_in *stream,
6962 struct audio_mmap_position *position)
6963{
6964 struct stream_in *in = (struct stream_in *)stream;
6965 ALOGVV("%s", __func__);
6966 if (position == NULL) {
6967 return -EINVAL;
6968 }
6969 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6970 return -ENOSYS;
6971 }
6972 if (in->pcm == NULL) {
6973 return -ENOSYS;
6974 }
6975 struct timespec ts = { 0, 0 };
6976 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6977 if (ret < 0) {
6978 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6979 return ret;
6980 }
Phil Burke0a86d12019-02-16 22:28:11 -08006981 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6982 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006983 return 0;
6984}
6985
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306986static int in_get_active_microphones(const struct audio_stream_in *stream,
6987 struct audio_microphone_characteristic_t *mic_array,
6988 size_t *mic_count) {
6989 struct stream_in *in = (struct stream_in *)stream;
6990 struct audio_device *adev = in->dev;
6991 ALOGVV("%s", __func__);
6992
6993 lock_input_stream(in);
6994 pthread_mutex_lock(&adev->lock);
6995 int ret = platform_get_active_microphones(adev->platform,
6996 audio_channel_count_from_in_mask(in->channel_mask),
6997 in->usecase, mic_array, mic_count);
6998 pthread_mutex_unlock(&adev->lock);
6999 pthread_mutex_unlock(&in->lock);
7000
7001 return ret;
7002}
7003
7004static int adev_get_microphones(const struct audio_hw_device *dev,
7005 struct audio_microphone_characteristic_t *mic_array,
7006 size_t *mic_count) {
7007 struct audio_device *adev = (struct audio_device *)dev;
7008 ALOGVV("%s", __func__);
7009
7010 pthread_mutex_lock(&adev->lock);
7011 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
7012 pthread_mutex_unlock(&adev->lock);
7013
7014 return ret;
7015}
juyuchendb308c22019-01-21 11:57:17 -07007016
7017static void in_update_sink_metadata(struct audio_stream_in *stream,
7018 const struct sink_metadata *sink_metadata) {
7019
7020 if (stream == NULL
7021 || sink_metadata == NULL
7022 || sink_metadata->tracks == NULL) {
7023 return;
7024 }
7025
7026 int error = 0;
7027 struct stream_in *in = (struct stream_in *)stream;
7028 struct audio_device *adev = in->dev;
7029 audio_devices_t device = AUDIO_DEVICE_NONE;
7030
7031 if (sink_metadata->track_count != 0)
7032 device = sink_metadata->tracks->dest_device;
7033
7034 lock_input_stream(in);
7035 pthread_mutex_lock(&adev->lock);
7036 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
7037
7038 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
7039 && device != AUDIO_DEVICE_NONE
7040 && adev->voice_tx_output != NULL) {
7041 /* Use the rx device from afe-proxy record to route voice call because
7042 there is no routing if tx device is on primary hal and rx device
7043 is on other hal during voice call. */
7044 adev->voice_tx_output->devices = device;
7045
7046 if (!voice_is_call_state_active(adev)) {
7047 if (adev->mode == AUDIO_MODE_IN_CALL) {
7048 adev->current_call_output = adev->voice_tx_output;
7049 error = voice_start_call(adev);
7050 if (error != 0)
7051 ALOGE("%s: start voice call failed %d", __func__, error);
7052 }
7053 } else {
7054 adev->current_call_output = adev->voice_tx_output;
7055 voice_update_devices_for_all_voice_usecases(adev);
7056 }
7057 }
7058
7059 pthread_mutex_unlock(&adev->lock);
7060 pthread_mutex_unlock(&in->lock);
7061}
7062
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307063int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07007064 audio_io_handle_t handle,
7065 audio_devices_t devices,
7066 audio_output_flags_t flags,
7067 struct audio_config *config,
7068 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04007069 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007070{
7071 struct audio_device *adev = (struct audio_device *)dev;
7072 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05307073 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007074 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007075 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05307076 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007077 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
7078 bool is_usb_dev = audio_is_usb_out_device(devices) &&
7079 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
7080 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007081 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07007082 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
7083 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007084 bool force_haptic_path =
7085 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007086 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007087
kunleizdff872d2018-08-20 14:40:33 +08007088 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08007089 is_usb_dev = false;
7090 devices = AUDIO_DEVICE_OUT_SPEAKER;
7091 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
7092 __func__, devices);
7093 }
7094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007095 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05307096
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007097 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
7098
Mingming Yin3a941d42016-02-17 18:08:05 -08007099 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04007100 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
7101 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307102
7103
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007104 if (!out) {
7105 return -ENOMEM;
7106 }
7107
Haynes Mathew George204045b2015-02-25 20:32:03 -08007108 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07007109 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307110 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08007111 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08007112 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
7113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007114 if (devices == AUDIO_DEVICE_NONE)
7115 devices = AUDIO_DEVICE_OUT_SPEAKER;
7116
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007117 out->flags = flags;
7118 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07007119 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07007120 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007121 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05307122 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05307123 if (out->channel_mask == AUDIO_CHANNEL_NONE)
7124 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
7125 else
7126 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07007127 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007128 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08007129 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307130 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307131 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307132 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007133 out->hal_output_suspend_supported = 0;
7134 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05307135 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05307136 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05307137 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007138
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05307139 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05307140 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07007141 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
7142
Aalique Grahame22e49102018-12-18 14:23:57 -08007143 if (direct_dev &&
7144 (audio_is_linear_pcm(out->format) ||
7145 config->format == AUDIO_FORMAT_DEFAULT) &&
7146 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
7147 audio_format_t req_format = config->format;
7148 audio_channel_mask_t req_channel_mask = config->channel_mask;
7149 uint32_t req_sample_rate = config->sample_rate;
7150
7151 pthread_mutex_lock(&adev->lock);
7152 if (is_hdmi) {
7153 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
7154 ret = read_hdmi_sink_caps(out);
7155 if (config->sample_rate == 0)
7156 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7157 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7158 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
7159 if (config->format == AUDIO_FORMAT_DEFAULT)
7160 config->format = AUDIO_FORMAT_PCM_16_BIT;
7161 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007162 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
7163 &config->format,
7164 &out->supported_formats[0],
7165 MAX_SUPPORTED_FORMATS,
7166 &config->channel_mask,
7167 &out->supported_channel_masks[0],
7168 MAX_SUPPORTED_CHANNEL_MASKS,
7169 &config->sample_rate,
7170 &out->supported_sample_rates[0],
7171 MAX_SUPPORTED_SAMPLE_RATES);
7172 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007173 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007174
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007175 pthread_mutex_unlock(&adev->lock);
7176 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007177 if (ret == -ENOSYS) {
7178 /* ignore and go with default */
7179 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007180 }
7181 // For MMAP NO IRQ, allow conversions in ADSP
7182 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
7183 goto error_open;
7184 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007185 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08007186 goto error_open;
7187 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007188
7189 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
7190 config->sample_rate = req_sample_rate;
7191 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
7192 config->channel_mask = req_channel_mask;
7193 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
7194 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08007195 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007196
7197 out->sample_rate = config->sample_rate;
7198 out->channel_mask = config->channel_mask;
7199 out->format = config->format;
7200 if (is_hdmi) {
7201 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7202 out->config = pcm_config_hdmi_multi;
7203 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7204 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7205 out->config = pcm_config_mmap_playback;
7206 out->stream.start = out_start;
7207 out->stream.stop = out_stop;
7208 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7209 out->stream.get_mmap_position = out_get_mmap_position;
7210 } else {
7211 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7212 out->config = pcm_config_hifi;
7213 }
7214
7215 out->config.rate = out->sample_rate;
7216 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7217 if (is_hdmi) {
7218 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7219 audio_bytes_per_sample(out->format));
7220 }
7221 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007222 }
7223
Derek Chenf6318be2017-06-12 17:16:24 -04007224 /* validate bus device address */
7225 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7226 /* extract car audio stream index */
7227 out->car_audio_stream =
7228 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
7229 if (out->car_audio_stream < 0) {
7230 ALOGE("%s: invalid car audio stream %x",
7231 __func__, out->car_audio_stream);
7232 ret = -EINVAL;
7233 goto error_open;
7234 }
7235 /* save car audio stream and address for bus device */
7236 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
7237 ALOGV("%s: address %s, car_audio_stream %x",
7238 __func__, out->address, out->car_audio_stream);
7239 }
7240
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007241 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007242 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007243 if (!voice_extn_is_compress_voip_supported()) {
7244 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7245 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007246 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7247 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007248 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7249 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007250 out->volume_l = INVALID_OUT_VOLUME;
7251 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007252
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007253 out->config = default_pcm_config_voip_copp;
7254 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7255 out->config.rate = out->sample_rate;
7256 }
7257 } else {
7258 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7259 voice_extn_compress_voip_is_active(out->dev)) &&
7260 (voice_extn_compress_voip_is_config_supported(config))) {
7261 ret = voice_extn_compress_voip_open_output_stream(out);
7262 if (ret != 0) {
7263 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7264 __func__, ret);
7265 goto error_open;
7266 }
7267 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007268 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007269 } else if (audio_is_linear_pcm(out->format) &&
7270 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7271 out->channel_mask = config->channel_mask;
7272 out->sample_rate = config->sample_rate;
7273 out->format = config->format;
7274 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7275 // does this change?
7276 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7277 out->config.rate = config->sample_rate;
7278 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7279 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7280 audio_bytes_per_sample(config->format));
7281 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007282 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307283 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307284 pthread_mutex_lock(&adev->lock);
7285 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7286 pthread_mutex_unlock(&adev->lock);
7287
7288 // reject offload during card offline to allow
7289 // fallback to s/w paths
7290 if (offline) {
7291 ret = -ENODEV;
7292 goto error_open;
7293 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007294
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007295 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7296 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7297 ALOGE("%s: Unsupported Offload information", __func__);
7298 ret = -EINVAL;
7299 goto error_open;
7300 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007301
Atul Khare3fa6e542017-08-09 00:56:17 +05307302 if (config->offload_info.format == 0)
7303 config->offload_info.format = config->format;
7304 if (config->offload_info.sample_rate == 0)
7305 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007306
Mingming Yin90310102013-11-13 16:57:00 -08007307 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307308 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007309 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007310 ret = -EINVAL;
7311 goto error_open;
7312 }
7313
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007314 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7315 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7316 (audio_extn_passthru_is_passthrough_stream(out)) &&
7317 !((config->sample_rate == 48000) ||
7318 (config->sample_rate == 96000) ||
7319 (config->sample_rate == 192000))) {
7320 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7321 __func__, config->sample_rate, config->offload_info.format);
7322 ret = -EINVAL;
7323 goto error_open;
7324 }
7325
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007326 out->compr_config.codec = (struct snd_codec *)
7327 calloc(1, sizeof(struct snd_codec));
7328
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007329 if (!out->compr_config.codec) {
7330 ret = -ENOMEM;
7331 goto error_open;
7332 }
7333
Dhananjay Kumarac341582017-02-23 23:42:25 +05307334 out->stream.pause = out_pause;
7335 out->stream.resume = out_resume;
7336 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307337 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307338 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007339 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307340 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007341 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307342 } else {
7343 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7344 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007345 }
vivek mehta446c3962015-09-14 10:57:35 -07007346
7347 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007348 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7349 config->format == 0 && config->sample_rate == 0 &&
7350 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007351 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007352 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7353 } else {
7354 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7355 ret = -EEXIST;
7356 goto error_open;
7357 }
vivek mehta446c3962015-09-14 10:57:35 -07007358 }
7359
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007360 if (config->offload_info.channel_mask)
7361 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007362 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007363 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007364 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007365 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307366 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007367 ret = -EINVAL;
7368 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007369 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007370
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007371 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007372 out->sample_rate = config->offload_info.sample_rate;
7373
Mingming Yin3ee55c62014-08-04 14:23:35 -07007374 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007375
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307376 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307377 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307378 audio_extn_dolby_send_ddp_endp_params(adev);
7379 audio_extn_dolby_set_dmid(adev);
7380 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007381
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007382 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007383 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007384 out->compr_config.codec->bit_rate =
7385 config->offload_info.bit_rate;
7386 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307387 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007388 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307389 /* Update bit width only for non passthrough usecases.
7390 * For passthrough usecases, the output will always be opened @16 bit
7391 */
7392 if (!audio_extn_passthru_is_passthrough_stream(out))
7393 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307394
7395 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7396 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7397 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7398
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007399 /*TODO: Do we need to change it for passthrough */
7400 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007401
Manish Dewangana6fc5442015-08-24 20:30:31 +05307402 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7403 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307404 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307405 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307406 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7407 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307408
7409 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7410 AUDIO_FORMAT_PCM) {
7411
7412 /*Based on platform support, configure appropriate alsa format for corresponding
7413 *hal input format.
7414 */
7415 out->compr_config.codec->format = hal_format_to_alsa(
7416 config->offload_info.format);
7417
Ashish Jain83a6cc22016-06-28 14:34:17 +05307418 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307419 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307420 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307421
Dhananjay Kumarac341582017-02-23 23:42:25 +05307422 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307423 *hal input format and alsa format might differ based on platform support.
7424 */
7425 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307426 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307427
7428 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7429
7430 /* Check if alsa session is configured with the same format as HAL input format,
7431 * if not then derive correct fragment size needed to accomodate the
7432 * conversion of HAL input format to alsa format.
7433 */
7434 audio_extn_utils_update_direct_pcm_fragment_size(out);
7435
7436 /*if hal input and output fragment size is different this indicates HAL input format is
7437 *not same as the alsa format
7438 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307439 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307440 /*Allocate a buffer to convert input data to the alsa configured format.
7441 *size of convert buffer is equal to the size required to hold one fragment size
7442 *worth of pcm data, this is because flinger does not write more than fragment_size
7443 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307444 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7445 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307446 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7447 ret = -ENOMEM;
7448 goto error_open;
7449 }
7450 }
7451 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7452 out->compr_config.fragment_size =
7453 audio_extn_passthru_get_buffer_size(&config->offload_info);
7454 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7455 } else {
7456 out->compr_config.fragment_size =
7457 platform_get_compress_offload_buffer_size(&config->offload_info);
7458 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7459 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007460
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307461 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7462 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7463 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007464 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307465 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007466
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307467 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7468 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7469 }
7470
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007471 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7472 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007473
Manish Dewangan69426c82017-01-30 17:35:36 +05307474 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7475 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7476 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7477 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7478 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7479 } else {
7480 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7481 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007482
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307483 memset(&out->channel_map_param, 0,
7484 sizeof(struct audio_out_channel_map_param));
7485
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007486 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307487 out->send_next_track_params = false;
7488 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007489 out->offload_state = OFFLOAD_STATE_IDLE;
7490 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007491 out->writeAt.tv_sec = 0;
7492 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007493
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007494 audio_extn_dts_create_state_notifier_node(out->usecase);
7495
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007496 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7497 __func__, config->offload_info.version,
7498 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307499
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307500 /* Check if DSD audio format is supported in codec
7501 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307502 */
7503
7504 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307505 (!platform_check_codec_dsd_support(adev->platform) ||
7506 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307507 ret = -EINVAL;
7508 goto error_open;
7509 }
7510
Ashish Jain5106d362016-05-11 19:23:33 +05307511 /* Disable gapless if any of the following is true
7512 * passthrough playback
7513 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307514 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307515 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307516 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307517 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007518 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307519 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307520 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307521 check_and_set_gapless_mode(adev, false);
7522 } else
7523 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007524
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307525 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007526 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7527 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307528 if (config->format == AUDIO_FORMAT_DSD) {
7529 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7530 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7531 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007532
7533 create_offload_callback_thread(out);
7534
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007535 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007536 switch (config->sample_rate) {
7537 case 0:
7538 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7539 break;
7540 case 8000:
7541 case 16000:
7542 case 48000:
7543 out->sample_rate = config->sample_rate;
7544 break;
7545 default:
7546 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7547 config->sample_rate);
7548 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7549 ret = -EINVAL;
7550 goto error_open;
7551 }
7552 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7553 switch (config->channel_mask) {
7554 case AUDIO_CHANNEL_NONE:
7555 case AUDIO_CHANNEL_OUT_STEREO:
7556 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7557 break;
7558 default:
7559 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7560 config->channel_mask);
7561 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7562 ret = -EINVAL;
7563 goto error_open;
7564 }
7565 switch (config->format) {
7566 case AUDIO_FORMAT_DEFAULT:
7567 case AUDIO_FORMAT_PCM_16_BIT:
7568 out->format = AUDIO_FORMAT_PCM_16_BIT;
7569 break;
7570 default:
7571 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7572 config->format);
7573 config->format = AUDIO_FORMAT_PCM_16_BIT;
7574 ret = -EINVAL;
7575 goto error_open;
7576 }
7577
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307578 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007579 if (ret != 0) {
7580 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007581 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007582 goto error_open;
7583 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007584 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007585 switch (config->sample_rate) {
7586 case 0:
7587 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7588 break;
7589 case 8000:
7590 case 16000:
7591 case 48000:
7592 out->sample_rate = config->sample_rate;
7593 break;
7594 default:
7595 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7596 config->sample_rate);
7597 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7598 ret = -EINVAL;
7599 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007600 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007601 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7602 switch (config->channel_mask) {
7603 case AUDIO_CHANNEL_NONE:
7604 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7605 break;
7606 case AUDIO_CHANNEL_OUT_STEREO:
7607 out->channel_mask = config->channel_mask;
7608 break;
7609 default:
7610 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7611 config->channel_mask);
7612 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7613 ret = -EINVAL;
7614 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007615 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007616 switch (config->format) {
7617 case AUDIO_FORMAT_DEFAULT:
7618 out->format = AUDIO_FORMAT_PCM_16_BIT;
7619 break;
7620 case AUDIO_FORMAT_PCM_16_BIT:
7621 out->format = config->format;
7622 break;
7623 default:
7624 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7625 config->format);
7626 config->format = AUDIO_FORMAT_PCM_16_BIT;
7627 ret = -EINVAL;
7628 break;
7629 }
7630 if (ret != 0)
7631 goto error_open;
7632
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007633 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7634 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007635 out->config.rate = out->sample_rate;
7636 out->config.channels =
7637 audio_channel_count_from_out_mask(out->channel_mask);
7638 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007639 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007640 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307641 unsigned int channels = 0;
7642 /*Update config params to default if not set by the caller*/
7643 if (config->sample_rate == 0)
7644 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7645 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7646 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7647 if (config->format == AUDIO_FORMAT_DEFAULT)
7648 config->format = AUDIO_FORMAT_PCM_16_BIT;
7649
7650 channels = audio_channel_count_from_out_mask(out->channel_mask);
7651
Varun Balaraje49253e2017-07-06 19:48:56 +05307652 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7653 out->usecase = get_interactive_usecase(adev);
7654 out->config = pcm_config_low_latency;
7655 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307656 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007657 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7658 out->flags);
7659 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007660 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7661 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7662 out->config = pcm_config_mmap_playback;
7663 out->stream.start = out_start;
7664 out->stream.stop = out_stop;
7665 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7666 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307667 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7668 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007669 out->hal_output_suspend_supported =
7670 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7671 out->dynamic_pm_qos_config_supported =
7672 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7673 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007674 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7675 } else {
7676 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7677 //the mixer path will be a string similar to "low-latency-playback resume"
7678 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7679 strlcat(out->pm_qos_mixer_path,
7680 " resume", MAX_MIXER_PATH_LEN);
7681 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7682 out->pm_qos_mixer_path);
7683 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307684 out->config = pcm_config_low_latency;
7685 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7686 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7687 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307688 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7689 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7690 if (out->config.period_size <= 0) {
7691 ALOGE("Invalid configuration period size is not valid");
7692 ret = -EINVAL;
7693 goto error_open;
7694 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007695 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7696 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7697 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007698 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7699 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7700 out->config = pcm_config_haptics_audio;
7701 if (force_haptic_path)
7702 adev->haptics_config = pcm_config_haptics_audio;
7703 else
7704 adev->haptics_config = pcm_config_haptics;
7705
7706 out->config.channels =
7707 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7708
7709 if (force_haptic_path) {
7710 out->config.channels = 1;
7711 adev->haptics_config.channels = 1;
7712 } else
7713 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Derek Chenf6318be2017-06-12 17:16:24 -04007714 } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7715 ret = audio_extn_auto_hal_open_output_stream(out);
7716 if (ret) {
7717 ALOGE("%s: Failed to open output stream for bus device", __func__);
7718 ret = -EINVAL;
7719 goto error_open;
7720 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307721 } else {
7722 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007723 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7724 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307725 }
7726 out->hal_ip_format = format = out->format;
7727 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7728 out->hal_op_format = pcm_format_to_hal(out->config.format);
7729 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7730 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007731 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307732 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307733 if (out->hal_ip_format != out->hal_op_format) {
7734 uint32_t buffer_size = out->config.period_size *
7735 format_to_bitwidth_table[out->hal_op_format] *
7736 out->config.channels;
7737 out->convert_buffer = calloc(1, buffer_size);
7738 if (out->convert_buffer == NULL){
7739 ALOGE("Allocation failed for convert buffer for size %d",
7740 out->compr_config.fragment_size);
7741 ret = -ENOMEM;
7742 goto error_open;
7743 }
7744 ALOGD("Convert buffer allocated of size %d", buffer_size);
7745 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007746 }
7747
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007748 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7749 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307750
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007751 /* TODO remove this hardcoding and check why width is zero*/
7752 if (out->bit_width == 0)
7753 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307754 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007755 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007756 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307757 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307758 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007759 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007760 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7761 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007762 if(adev->primary_output == NULL)
7763 adev->primary_output = out;
7764 else {
7765 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007766 ret = -EEXIST;
7767 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007768 }
7769 }
7770
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007771 /* Check if this usecase is already existing */
7772 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007773 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7774 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007775 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007776 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007777 ret = -EEXIST;
7778 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007779 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007780
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007781 pthread_mutex_unlock(&adev->lock);
7782
7783 out->stream.common.get_sample_rate = out_get_sample_rate;
7784 out->stream.common.set_sample_rate = out_set_sample_rate;
7785 out->stream.common.get_buffer_size = out_get_buffer_size;
7786 out->stream.common.get_channels = out_get_channels;
7787 out->stream.common.get_format = out_get_format;
7788 out->stream.common.set_format = out_set_format;
7789 out->stream.common.standby = out_standby;
7790 out->stream.common.dump = out_dump;
7791 out->stream.common.set_parameters = out_set_parameters;
7792 out->stream.common.get_parameters = out_get_parameters;
7793 out->stream.common.add_audio_effect = out_add_audio_effect;
7794 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7795 out->stream.get_latency = out_get_latency;
7796 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007797#ifdef NO_AUDIO_OUT
7798 out->stream.write = out_write_for_no_output;
7799#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007800 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007801#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007802 out->stream.get_render_position = out_get_render_position;
7803 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007804 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007805
Haynes Mathew George16081042017-05-31 17:16:49 -07007806 if (out->realtime)
7807 out->af_period_multiplier = af_period_multiplier;
7808 else
7809 out->af_period_multiplier = 1;
7810
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007811 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007812 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007813 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007814
7815 config->format = out->stream.common.get_format(&out->stream.common);
7816 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7817 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307818 register_format(out->format, out->supported_formats);
7819 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7820 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007821
Aalique Grahame22e49102018-12-18 14:23:57 -08007822 out->error_log = error_log_create(
7823 ERROR_LOG_ENTRIES,
7824 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7825
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307826 /*
7827 By locking output stream before registering, we allow the callback
7828 to update stream's state only after stream's initial state is set to
7829 adev state.
7830 */
7831 lock_output_stream(out);
7832 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7833 pthread_mutex_lock(&adev->lock);
7834 out->card_status = adev->card_status;
7835 pthread_mutex_unlock(&adev->lock);
7836 pthread_mutex_unlock(&out->lock);
7837
Aalique Grahame22e49102018-12-18 14:23:57 -08007838 stream_app_type_cfg_init(&out->app_type_cfg);
7839
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007840 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307841 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007842 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007843
7844 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7845 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7846 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007847 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307848 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007849 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007850 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307851 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
7852 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007853 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7854 out->usecase, PCM_PLAYBACK);
7855 hdlr_stream_cfg.flags = out->flags;
7856 hdlr_stream_cfg.type = PCM_PLAYBACK;
7857 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7858 &hdlr_stream_cfg);
7859 if (ret) {
7860 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7861 out->adsp_hdlr_stream_handle = NULL;
7862 }
7863 }
Gangadhar Sb0210342019-02-22 17:39:41 +05307864 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
7865 is_direct_passthough, false);
7866 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
7867 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007868 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007869 if (ret < 0) {
7870 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7871 out->ip_hdlr_handle = NULL;
7872 }
7873 }
Derek Chenf939fb72018-11-13 13:34:41 -08007874
7875 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7876 calloc(1, sizeof(streams_output_ctxt_t));
7877 if (out_ctxt == NULL) {
7878 ALOGE("%s fail to allocate output ctxt", __func__);
7879 ret = -ENOMEM;
7880 goto error_open;
7881 }
7882 out_ctxt->output = out;
7883
7884 pthread_mutex_lock(&adev->lock);
7885 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7886 pthread_mutex_unlock(&adev->lock);
7887
Eric Laurent994a6932013-07-17 11:51:42 -07007888 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007889 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007890
7891error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307892 if (out->convert_buffer)
7893 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007894 free(out);
7895 *stream_out = NULL;
7896 ALOGD("%s: exit: ret %d", __func__, ret);
7897 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007898}
7899
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307900void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007901 struct audio_stream_out *stream)
7902{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007903 struct stream_out *out = (struct stream_out *)stream;
7904 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007905 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007906
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007907 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307908
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307909 // must deregister from sndmonitor first to prevent races
7910 // between the callback and close_stream
7911 audio_extn_snd_mon_unregister_listener(out);
7912
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007913 /* close adsp hdrl session before standby */
7914 if (out->adsp_hdlr_stream_handle) {
7915 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7916 if (ret)
7917 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7918 out->adsp_hdlr_stream_handle = NULL;
7919 }
7920
Manish Dewangan21a850a2017-08-14 12:03:55 +05307921 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007922 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7923 out->ip_hdlr_handle = NULL;
7924 }
7925
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007926 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307927 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007928 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307929 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307930 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007931 if(ret != 0)
7932 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7933 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007934 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007935 out_standby(&stream->common);
7936
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007937 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007938 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007939 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007940 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007941 if (out->compr_config.codec != NULL)
7942 free(out->compr_config.codec);
7943 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007944
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307945 out->a2dp_compress_mute = false;
7946
Varun Balaraje49253e2017-07-06 19:48:56 +05307947 if (is_interactive_usecase(out->usecase))
7948 free_interactive_usecase(adev, out->usecase);
7949
Ashish Jain83a6cc22016-06-28 14:34:17 +05307950 if (out->convert_buffer != NULL) {
7951 free(out->convert_buffer);
7952 out->convert_buffer = NULL;
7953 }
7954
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007955 if (adev->voice_tx_output == out)
7956 adev->voice_tx_output = NULL;
7957
Aalique Grahame22e49102018-12-18 14:23:57 -08007958 error_log_destroy(out->error_log);
7959 out->error_log = NULL;
7960
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307961 if (adev->primary_output == out)
7962 adev->primary_output = NULL;
7963
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007964 pthread_cond_destroy(&out->cond);
7965 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007966
7967 pthread_mutex_lock(&adev->lock);
7968 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7969 if (out_ctxt != NULL) {
7970 list_remove(&out_ctxt->list);
7971 free(out_ctxt);
7972 } else {
7973 ALOGW("%s, output stream already closed", __func__);
7974 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007975 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007976 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007977 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007978}
7979
7980static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7981{
7982 struct audio_device *adev = (struct audio_device *)dev;
7983 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007984 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007985 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007986 int ret;
7987 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007988 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08007989 struct listnode *node;
7990 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007991
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007992 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007993 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007994
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307995 if (!parms)
7996 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307997
Zhou Songd6d71752019-05-21 18:08:51 +08007998 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307999 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
8000 if (ret >= 0) {
8001 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08008002 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308003 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08008004 } else {
8005 ALOGD("sco is off, reset sco and route device to handset/mic");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308006 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08008007 audio_extn_sco_reset_configuration();
8008 list_for_each(node, &adev->usecase_list) {
8009 usecase = node_to_item(node, struct audio_usecase, list);
8010 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
8011 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
8012 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
8013 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
8014 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
8015 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
8016 else
8017 continue;
8018 select_devices(adev, usecase->id);
8019 }
8020 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308021 }
8022
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008023 status = voice_set_parameters(adev, parms);
8024 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008025 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008026
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008027 status = platform_set_parameters(adev->platform, parms);
8028 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008029 goto done;
8030
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008031 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
8032 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07008033 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008034 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8035 adev->bluetooth_nrec = true;
8036 else
8037 adev->bluetooth_nrec = false;
8038 }
8039
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008040 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
8041 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008042 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8043 adev->screen_off = false;
8044 else
8045 adev->screen_off = true;
8046 }
8047
Eric Laurent4b084132018-10-19 17:33:43 -07008048 ret = str_parms_get_int(parms, "rotation", &val);
8049 if (ret >= 0) {
8050 bool reverse_speakers = false;
8051 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8052 switch (val) {
8053 // FIXME: note that the code below assumes that the speakers are in the correct placement
8054 // relative to the user when the device is rotated 90deg from its default rotation. This
8055 // assumption is device-specific, not platform-specific like this code.
8056 case 270:
8057 reverse_speakers = true;
8058 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
8059 break;
8060 case 0:
8061 case 180:
8062 camera_rotation = CAMERA_ROTATION_PORTRAIT;
8063 break;
8064 case 90:
8065 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
8066 break;
8067 default:
8068 ALOGE("%s: unexpected rotation of %d", __func__, val);
8069 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008070 }
Eric Laurent4b084132018-10-19 17:33:43 -07008071 if (status == 0) {
8072 // check and set swap
8073 // - check if orientation changed and speaker active
8074 // - set rotation and cache the rotation value
8075 adev->camera_orientation =
8076 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
8077 if (!audio_extn_is_maxx_audio_enabled())
8078 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
8079 }
8080 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07008081
Mingming Yin514a8bc2014-07-29 15:22:21 -07008082 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
8083 if (ret >= 0) {
8084 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
8085 adev->bt_wb_speech_enabled = true;
8086 else
8087 adev->bt_wb_speech_enabled = false;
8088 }
8089
Zhou Song12c29502019-03-16 10:37:18 +08008090 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
8091 if (ret >= 0) {
8092 val = atoi(value);
8093 adev->swb_speech_mode = val;
8094 }
8095
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008096 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
8097 if (ret >= 0) {
8098 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308099 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08008100 if (audio_is_output_device(val) &&
8101 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008102 ALOGV("cache new ext disp type and edid");
8103 ret = platform_get_ext_disp_type(adev->platform);
8104 if (ret < 0) {
8105 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05308106 } else {
8107 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07008108 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308109 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07008110 /*
8111 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
8112 * Per AudioPolicyManager, USB device is higher priority than WFD.
8113 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
8114 * If WFD use case occupies AFE proxy, it may result unintended behavior while
8115 * starting voice call on USB
8116 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008117 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308118 if (ret >= 0)
8119 audio_extn_usb_add_device(device, atoi(value));
8120
Zhou Song6f862822017-11-06 17:27:57 +08008121 if (!audio_extn_usb_is_tunnel_supported()) {
8122 ALOGV("detected USB connect .. disable proxy");
8123 adev->allow_afe_proxy_usage = false;
8124 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008125 }
8126 }
8127
8128 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
8129 if (ret >= 0) {
8130 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308131 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07008132 /*
8133 * The HDMI / Displayport disconnect handling has been moved to
8134 * audio extension to ensure that its parameters are not
8135 * invalidated prior to updating sysfs of the disconnect event
8136 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
8137 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308138 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08008139 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05308140 if (ret >= 0)
8141 audio_extn_usb_remove_device(device, atoi(value));
8142
Zhou Song6f862822017-11-06 17:27:57 +08008143 if (!audio_extn_usb_is_tunnel_supported()) {
8144 ALOGV("detected USB disconnect .. enable proxy");
8145 adev->allow_afe_proxy_usage = true;
8146 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07008147 }
8148 }
8149
Aalique Grahame22e49102018-12-18 14:23:57 -08008150 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008151 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08008152
8153 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08008154 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308155 struct audio_usecase *usecase;
8156 struct listnode *node;
8157 list_for_each(node, &adev->usecase_list) {
8158 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05308159 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07008160 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308161 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08008162
8163 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308164 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08008165 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308166 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308167 //force device switch to re configure encoder
8168 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308169 audio_extn_a2dp_set_handoff_mode(false);
8170 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05308171 break;
8172 }
8173 }
8174 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008175
8176 //handle vr audio setparam
8177 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8178 value, sizeof(value));
8179 if (ret >= 0) {
8180 ALOGI("Setting vr mode to be %s", value);
8181 if (!strncmp(value, "true", 4)) {
8182 adev->vr_audio_mode_enabled = true;
8183 ALOGI("Setting vr mode to true");
8184 } else if (!strncmp(value, "false", 5)) {
8185 adev->vr_audio_mode_enabled = false;
8186 ALOGI("Setting vr mode to false");
8187 } else {
8188 ALOGI("wrong vr mode set");
8189 }
8190 }
8191
Eric Laurent4b084132018-10-19 17:33:43 -07008192 //FIXME: to be replaced by proper video capture properties API
8193 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
8194 if (ret >= 0) {
8195 int camera_facing = CAMERA_FACING_BACK;
8196 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
8197 camera_facing = CAMERA_FACING_FRONT;
8198 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
8199 camera_facing = CAMERA_FACING_BACK;
8200 else {
8201 ALOGW("%s: invalid camera facing value: %s", __func__, value);
8202 goto done;
8203 }
8204 adev->camera_orientation =
8205 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
8206 struct audio_usecase *usecase;
8207 struct listnode *node;
8208 list_for_each(node, &adev->usecase_list) {
8209 usecase = node_to_item(node, struct audio_usecase, list);
8210 struct stream_in *in = usecase->stream.in;
8211 if (usecase->type == PCM_CAPTURE && in != NULL &&
8212 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
8213 select_devices(adev, in->usecase);
8214 }
8215 }
8216 }
8217
Naresh Tannirucd2353e2016-08-19 00:37:25 +05308218 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08008219done:
8220 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008221 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05308222error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008223 ALOGV("%s: exit with code(%d)", __func__, status);
8224 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008225}
8226
8227static char* adev_get_parameters(const struct audio_hw_device *dev,
8228 const char *keys)
8229{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308230 ALOGD("%s:%s", __func__, keys);
8231
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008232 struct audio_device *adev = (struct audio_device *)dev;
8233 struct str_parms *reply = str_parms_create();
8234 struct str_parms *query = str_parms_create_str(keys);
8235 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308236 char value[256] = {0};
8237 int ret = 0;
8238
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008239 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008240 if (reply) {
8241 str_parms_destroy(reply);
8242 }
8243 if (query) {
8244 str_parms_destroy(query);
8245 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008246 ALOGE("adev_get_parameters: failed to create query or reply");
8247 return NULL;
8248 }
8249
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008250 //handle vr audio getparam
8251
8252 ret = str_parms_get_str(query,
8253 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8254 value, sizeof(value));
8255
8256 if (ret >= 0) {
8257 bool vr_audio_enabled = false;
8258 pthread_mutex_lock(&adev->lock);
8259 vr_audio_enabled = adev->vr_audio_mode_enabled;
8260 pthread_mutex_unlock(&adev->lock);
8261
8262 ALOGI("getting vr mode to %d", vr_audio_enabled);
8263
8264 if (vr_audio_enabled) {
8265 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8266 "true");
8267 goto exit;
8268 } else {
8269 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8270 "false");
8271 goto exit;
8272 }
8273 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008274
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008275 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008276 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008277 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008278 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008279 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308280 pthread_mutex_unlock(&adev->lock);
8281
Naresh Tannirud7205b62014-06-20 02:54:48 +05308282exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008283 str = str_parms_to_str(reply);
8284 str_parms_destroy(query);
8285 str_parms_destroy(reply);
8286
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308287 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008288 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008289}
8290
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008291static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008292{
8293 return 0;
8294}
8295
8296static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8297{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008298 int ret;
8299 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008300
8301 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8302
Haynes Mathew George5191a852013-09-11 14:19:36 -07008303 pthread_mutex_lock(&adev->lock);
8304 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008305 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008306 pthread_mutex_unlock(&adev->lock);
8307 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008308}
8309
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008310static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8311 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008312{
8313 return -ENOSYS;
8314}
8315
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008316static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8317 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008318{
8319 return -ENOSYS;
8320}
8321
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008322static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8323 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008324{
8325 return -ENOSYS;
8326}
8327
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008328static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8329 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008330{
8331 return -ENOSYS;
8332}
8333
8334static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8335{
8336 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008337 struct listnode *node;
8338 struct audio_usecase *usecase = NULL;
8339 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008340
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008341 pthread_mutex_lock(&adev->lock);
8342 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008343 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008344 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008345 if (voice_is_in_call(adev) &&
8346 (mode == AUDIO_MODE_NORMAL ||
8347 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008348 list_for_each(node, &adev->usecase_list) {
8349 usecase = node_to_item(node, struct audio_usecase, list);
8350 if (usecase->type == VOICE_CALL)
8351 break;
8352 }
8353 if (usecase &&
8354 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8355 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8356 true);
8357 if (ret != 0) {
8358 /* default service interval was successfully updated,
8359 reopen USB backend with new service interval */
8360 check_usecases_codec_backend(adev,
8361 usecase,
8362 usecase->out_snd_device);
8363 }
8364 }
8365
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008366 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008367 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008368 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008369 // restore device for other active usecases after stop call
8370 list_for_each(node, &adev->usecase_list) {
8371 usecase = node_to_item(node, struct audio_usecase, list);
8372 select_devices(adev, usecase->id);
8373 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008374 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008375 }
8376 pthread_mutex_unlock(&adev->lock);
8377 return 0;
8378}
8379
8380static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8381{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008382 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008383 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008384
8385 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008386 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008387 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008388
Derek Chend2530072014-11-24 12:39:14 -08008389 if (adev->ext_hw_plugin)
8390 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008391
8392 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008393 pthread_mutex_unlock(&adev->lock);
8394
8395 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008396}
8397
8398static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8399{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008400 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008401 return 0;
8402}
8403
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008404static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008405 const struct audio_config *config)
8406{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008407 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008408
Aalique Grahame22e49102018-12-18 14:23:57 -08008409 /* Don't know if USB HIFI in this context so use true to be conservative */
8410 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8411 true /*is_usb_hifi */) != 0)
8412 return 0;
8413
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008414 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8415 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008416}
8417
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008418static bool adev_input_allow_hifi_record(struct audio_device *adev,
8419 audio_devices_t devices,
8420 audio_input_flags_t flags,
8421 audio_source_t source) {
8422 const bool allowed = true;
8423
8424 if (!audio_is_usb_in_device(devices))
8425 return !allowed;
8426
8427 switch (flags) {
8428 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008429 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008430 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8431 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008432 default:
8433 return !allowed;
8434 }
8435
8436 switch (source) {
8437 case AUDIO_SOURCE_DEFAULT:
8438 case AUDIO_SOURCE_MIC:
8439 case AUDIO_SOURCE_UNPROCESSED:
8440 break;
8441 default:
8442 return !allowed;
8443 }
8444
8445 switch (adev->mode) {
8446 case 0:
8447 break;
8448 default:
8449 return !allowed;
8450 }
8451
8452 return allowed;
8453}
8454
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008455static int adev_update_voice_comm_input_stream(struct stream_in *in,
8456 struct audio_config *config)
8457{
8458 bool valid_rate = (config->sample_rate == 8000 ||
8459 config->sample_rate == 16000 ||
8460 config->sample_rate == 32000 ||
8461 config->sample_rate == 48000);
8462 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8463
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008464 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008465 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008466 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8467 in->config = default_pcm_config_voip_copp;
8468 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8469 DEFAULT_VOIP_BUF_DURATION_MS,
8470 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008471 } else {
8472 ALOGW("%s No valid input in voip, use defaults"
8473 "sample rate %u, channel mask 0x%X",
8474 __func__, config->sample_rate, in->channel_mask);
8475 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008476 in->config.rate = config->sample_rate;
8477 in->sample_rate = config->sample_rate;
8478 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008479 //XXX needed for voice_extn_compress_voip_open_input_stream
8480 in->config.rate = config->sample_rate;
8481 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8482 voice_extn_compress_voip_is_active(in->dev)) &&
8483 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8484 valid_rate && valid_ch) {
8485 voice_extn_compress_voip_open_input_stream(in);
8486 // update rate entries to match config from AF
8487 in->config.rate = config->sample_rate;
8488 in->sample_rate = config->sample_rate;
8489 } else {
8490 ALOGW("%s compress voip not active, use defaults", __func__);
8491 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008492 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008493 return 0;
8494}
8495
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008496static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008497 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008498 audio_devices_t devices,
8499 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008500 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308501 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008502 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008503 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008504{
8505 struct audio_device *adev = (struct audio_device *)dev;
8506 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008507 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008508 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008509 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308510 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008511 bool is_usb_dev = audio_is_usb_in_device(devices);
8512 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8513 devices,
8514 flags,
8515 source);
Andy Hung94320602018-10-29 18:31:12 -07008516 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8517 " sample_rate %u, channel_mask %#x, format %#x",
8518 __func__, flags, is_usb_dev, may_use_hifi_record,
8519 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308520
kunleizdff872d2018-08-20 14:40:33 +08008521 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008522 is_usb_dev = false;
8523 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8524 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8525 __func__, devices);
8526 }
8527
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008528 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008529
8530 if (!(is_usb_dev && may_use_hifi_record)) {
8531 if (config->sample_rate == 0)
8532 config->sample_rate = 48000;
8533 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8534 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8535 if (config->format == AUDIO_FORMAT_DEFAULT)
8536 config->format = AUDIO_FORMAT_PCM_16_BIT;
8537
8538 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8539
Aalique Grahame22e49102018-12-18 14:23:57 -08008540 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8541 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008542 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308543 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008544
8545 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008546
8547 if (!in) {
8548 ALOGE("failed to allocate input stream");
8549 return -ENOMEM;
8550 }
8551
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308552 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308553 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8554 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008555 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008556 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008558 in->stream.common.get_sample_rate = in_get_sample_rate;
8559 in->stream.common.set_sample_rate = in_set_sample_rate;
8560 in->stream.common.get_buffer_size = in_get_buffer_size;
8561 in->stream.common.get_channels = in_get_channels;
8562 in->stream.common.get_format = in_get_format;
8563 in->stream.common.set_format = in_set_format;
8564 in->stream.common.standby = in_standby;
8565 in->stream.common.dump = in_dump;
8566 in->stream.common.set_parameters = in_set_parameters;
8567 in->stream.common.get_parameters = in_get_parameters;
8568 in->stream.common.add_audio_effect = in_add_audio_effect;
8569 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8570 in->stream.set_gain = in_set_gain;
8571 in->stream.read = in_read;
8572 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008573 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308574 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008575 in->stream.set_microphone_direction = in_set_microphone_direction;
8576 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008577 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008578
8579 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008580 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008581 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008582 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008583 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008584 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008585 in->bit_width = 16;
8586 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008587 in->direction = MIC_DIRECTION_UNSPECIFIED;
8588 in->zoom = 0;
Carter Hsu2e429db2019-05-14 18:50:52 +08008589 list_init(&in->aec_list);
8590 list_init(&in->ns_list);
Haynes Mathew George46740472017-10-27 18:40:12 -07008591
Andy Hung94320602018-10-29 18:31:12 -07008592 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008593 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8594 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8595 /* Force channel config requested to mono if incall
8596 record is being requested for only uplink/downlink */
8597 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8598 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8599 ret = -EINVAL;
8600 goto err_open;
8601 }
8602 }
8603
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008604 if (is_usb_dev && may_use_hifi_record) {
8605 /* HiFi record selects an appropriate format, channel, rate combo
8606 depending on sink capabilities*/
8607 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8608 &config->format,
8609 &in->supported_formats[0],
8610 MAX_SUPPORTED_FORMATS,
8611 &config->channel_mask,
8612 &in->supported_channel_masks[0],
8613 MAX_SUPPORTED_CHANNEL_MASKS,
8614 &config->sample_rate,
8615 &in->supported_sample_rates[0],
8616 MAX_SUPPORTED_SAMPLE_RATES);
8617 if (ret != 0) {
8618 ret = -EINVAL;
8619 goto err_open;
8620 }
8621 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008622 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308623 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308624 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8625 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8626 in->config.format = PCM_FORMAT_S32_LE;
8627 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308628 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8629 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8630 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8631 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8632 bool ret_error = false;
8633 in->bit_width = 24;
8634 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8635 from HAL is 24_packed and 8_24
8636 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8637 24_packed return error indicating supported format is 24_packed
8638 *> In case of any other source requesting 24 bit or float return error
8639 indicating format supported is 16 bit only.
8640
8641 on error flinger will retry with supported format passed
8642 */
8643 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8644 (source != AUDIO_SOURCE_CAMCORDER)) {
8645 config->format = AUDIO_FORMAT_PCM_16_BIT;
8646 if (config->sample_rate > 48000)
8647 config->sample_rate = 48000;
8648 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008649 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8650 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308651 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8652 ret_error = true;
8653 }
8654
8655 if (ret_error) {
8656 ret = -EINVAL;
8657 goto err_open;
8658 }
8659 }
8660
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008661 in->channel_mask = config->channel_mask;
8662 in->format = config->format;
8663
8664 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308665
8666 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8667 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8668 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8669 else {
8670 ret = -EINVAL;
8671 goto err_open;
8672 }
8673 }
8674
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008675 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8676 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8677 is_low_latency = true;
8678#if LOW_LATENCY_CAPTURE_USE_CASE
8679 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8680#endif
8681 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008682 if (!in->realtime) {
8683 in->config = pcm_config_audio_capture;
8684 frame_size = audio_stream_in_frame_size(&in->stream);
8685 buffer_size = get_input_buffer_size(config->sample_rate,
8686 config->format,
8687 channel_count,
8688 is_low_latency);
8689 in->config.period_size = buffer_size / frame_size;
8690 in->config.rate = config->sample_rate;
8691 in->af_period_multiplier = 1;
8692 } else {
8693 // period size is left untouched for rt mode playback
8694 in->config = pcm_config_audio_capture_rt;
8695 in->af_period_multiplier = af_period_multiplier;
8696 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008697 }
8698
8699 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8700 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8701 in->realtime = 0;
8702 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8703 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008704 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008705 in->stream.start = in_start;
8706 in->stream.stop = in_stop;
8707 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8708 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008709 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8710 } else if (in->realtime) {
8711 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008712 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008713 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008714 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008715 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8716 in->config = pcm_config_audio_capture;
8717 frame_size = audio_stream_in_frame_size(&in->stream);
8718 buffer_size = get_input_buffer_size(config->sample_rate,
8719 config->format,
8720 channel_count,
8721 false /*is_low_latency*/);
8722 in->config.period_size = buffer_size / frame_size;
8723 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008724 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008725 switch (config->format) {
8726 case AUDIO_FORMAT_PCM_32_BIT:
8727 in->bit_width = 32;
8728 break;
8729 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8730 case AUDIO_FORMAT_PCM_8_24_BIT:
8731 in->bit_width = 24;
8732 break;
8733 default:
8734 in->bit_width = 16;
8735 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008736 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308737 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008738 if (config->sample_rate == 0)
8739 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8740 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8741 config->sample_rate != 8000) {
8742 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8743 ret = -EINVAL;
8744 goto err_open;
8745 }
8746 if (config->format == AUDIO_FORMAT_DEFAULT)
8747 config->format = AUDIO_FORMAT_PCM_16_BIT;
8748 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8749 config->format = AUDIO_FORMAT_PCM_16_BIT;
8750 ret = -EINVAL;
8751 goto err_open;
8752 }
8753
8754 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8755 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008756 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008757 in->af_period_multiplier = 1;
8758 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8759 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8760 (config->sample_rate == 8000 ||
8761 config->sample_rate == 16000 ||
8762 config->sample_rate == 32000 ||
8763 config->sample_rate == 48000) &&
8764 channel_count == 1) {
8765 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8766 in->config = pcm_config_audio_capture;
8767 frame_size = audio_stream_in_frame_size(&in->stream);
8768 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8769 config->sample_rate,
8770 config->format,
8771 channel_count, false /*is_low_latency*/);
8772 in->config.period_size = buffer_size / frame_size;
8773 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8774 in->config.rate = config->sample_rate;
8775 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008776 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308777 int ret_val;
8778 pthread_mutex_lock(&adev->lock);
8779 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8780 in, config, &channel_mask_updated);
8781 pthread_mutex_unlock(&adev->lock);
8782
8783 if (!ret_val) {
8784 if (channel_mask_updated == true) {
8785 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8786 __func__, config->channel_mask);
8787 ret = -EINVAL;
8788 goto err_open;
8789 }
8790 ALOGD("%s: created multi-channel session succesfully",__func__);
8791 } else if (audio_extn_compr_cap_enabled() &&
8792 audio_extn_compr_cap_format_supported(config->format) &&
8793 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8794 audio_extn_compr_cap_init(in);
8795 } else if (audio_extn_cin_applicable_stream(in)) {
8796 ret = audio_extn_cin_configure_input_stream(in);
8797 if (ret)
8798 goto err_open;
8799 } else {
8800 in->config = pcm_config_audio_capture;
8801 in->config.rate = config->sample_rate;
8802 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308803 in->format = config->format;
8804 frame_size = audio_stream_in_frame_size(&in->stream);
8805 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008806 config->format,
8807 channel_count,
8808 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008809 /* prevent division-by-zero */
8810 if (frame_size == 0) {
8811 ALOGE("%s: Error frame_size==0", __func__);
8812 ret = -EINVAL;
8813 goto err_open;
8814 }
8815
Revathi Uddarajud2634032017-12-07 14:42:34 +05308816 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008817 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008818
Revathi Uddarajud2634032017-12-07 14:42:34 +05308819 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8820 /* optionally use VOIP usecase depending on config(s) */
8821 ret = adev_update_voice_comm_input_stream(in, config);
8822 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008823
Revathi Uddarajud2634032017-12-07 14:42:34 +05308824 if (ret) {
8825 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8826 goto err_open;
8827 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008828 }
Samyak Jainc37062f2019-04-25 18:41:06 +05308829 if (audio_extn_is_concurrent_capture_enabled()) {
8830 /* Acquire lock to avoid two concurrent use cases initialized to
8831 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08008832
Samyak Jainc37062f2019-04-25 18:41:06 +05308833 if (in->usecase == USECASE_AUDIO_RECORD) {
8834 pthread_mutex_lock(&adev->lock);
8835 if (!(adev->pcm_record_uc_state)) {
8836 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8837 adev->pcm_record_uc_state = 1;
8838 pthread_mutex_unlock(&adev->lock);
8839 } else {
8840 pthread_mutex_unlock(&adev->lock);
8841 /* Assign compress record use case for second record */
8842 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8843 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8844 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8845 if (audio_extn_cin_applicable_stream(in)) {
8846 in->sample_rate = config->sample_rate;
8847 ret = audio_extn_cin_configure_input_stream(in);
8848 if (ret)
8849 goto err_open;
8850 }
8851 }
8852 }
kunleiz28c73e72019-03-27 17:24:04 +08008853 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008854 }
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008855
8856 in->config.channels = channel_count;
8857 in->sample_rate = in->config.rate;
8858
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308859 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8860 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008861 devices, flags, in->format,
8862 in->sample_rate, in->bit_width,
8863 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308864 register_format(in->format, in->supported_formats);
8865 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8866 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308867
Aalique Grahame22e49102018-12-18 14:23:57 -08008868 in->error_log = error_log_create(
8869 ERROR_LOG_ENTRIES,
8870 1000000000 /* aggregate consecutive identical errors within one second */);
8871
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008872 /* This stream could be for sound trigger lab,
8873 get sound trigger pcm if present */
8874 audio_extn_sound_trigger_check_and_get_session(in);
8875
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308876 lock_input_stream(in);
8877 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8878 pthread_mutex_lock(&adev->lock);
8879 in->card_status = adev->card_status;
8880 pthread_mutex_unlock(&adev->lock);
8881 pthread_mutex_unlock(&in->lock);
8882
Aalique Grahame22e49102018-12-18 14:23:57 -08008883 stream_app_type_cfg_init(&in->app_type_cfg);
8884
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008885 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008886
8887 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8888 calloc(1, sizeof(streams_input_ctxt_t));
8889 if (in_ctxt == NULL) {
8890 ALOGE("%s fail to allocate input ctxt", __func__);
8891 ret = -ENOMEM;
8892 goto err_open;
8893 }
8894 in_ctxt->input = in;
8895
8896 pthread_mutex_lock(&adev->lock);
8897 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8898 pthread_mutex_unlock(&adev->lock);
8899
Eric Laurent994a6932013-07-17 11:51:42 -07008900 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008901 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008902
8903err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05308904 if (in->usecase == USECASE_AUDIO_RECORD) {
8905 pthread_mutex_lock(&adev->lock);
8906 adev->pcm_record_uc_state = 0;
8907 pthread_mutex_unlock(&adev->lock);
8908 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008909 free(in);
8910 *stream_in = NULL;
8911 return ret;
8912}
8913
8914static void adev_close_input_stream(struct audio_hw_device *dev,
8915 struct audio_stream_in *stream)
8916{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008917 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008918 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008919 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308920
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308921 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008922
kunleiz70e57612018-12-28 17:50:23 +08008923 /* must deregister from sndmonitor first to prevent races
8924 * between the callback and close_stream
8925 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308926 audio_extn_snd_mon_unregister_listener(stream);
8927
kunleiz70e57612018-12-28 17:50:23 +08008928 /* Disable echo reference if there are no active input, hfp call
8929 * and sound trigger while closing input stream
8930 */
Eric Laurent637e2d42018-11-15 12:24:31 -08008931 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08008932 !audio_extn_hfp_is_active(adev) &&
8933 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008934 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008935 else
8936 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308937
Pallavid7c7a272018-01-16 11:22:55 +05308938 if (in == NULL) {
8939 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8940 return;
8941 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08008942 error_log_destroy(in->error_log);
8943 in->error_log = NULL;
8944
Pallavid7c7a272018-01-16 11:22:55 +05308945
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008946 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308947 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008948 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308949 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008950 if (ret != 0)
8951 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8952 __func__, ret);
8953 } else
8954 in_standby(&stream->common);
8955
Revathi Uddarajud2634032017-12-07 14:42:34 +05308956 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308957 if (in->usecase == USECASE_AUDIO_RECORD) {
8958 adev->pcm_record_uc_state = 0;
8959 }
8960
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008961 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008962 audio_extn_ssr_deinit();
8963 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008964
Garmond Leunge2433c32017-09-28 21:51:22 -07008965 if (audio_extn_ffv_get_stream() == in) {
8966 audio_extn_ffv_stream_deinit();
8967 }
8968
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308969 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008970 audio_extn_compr_cap_format_supported(in->config.format))
8971 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308972
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308973 if (audio_extn_cin_attached_usecase(in->usecase))
8974 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008975
Mingming Yinfd7607b2016-01-22 12:48:44 -08008976 if (in->is_st_session) {
8977 ALOGV("%s: sound trigger pcm stop lab", __func__);
8978 audio_extn_sound_trigger_stop_lab(in);
8979 }
Derek Chenf939fb72018-11-13 13:34:41 -08008980 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8981 if (in_ctxt != NULL) {
8982 list_remove(&in_ctxt->list);
8983 free(in_ctxt);
8984 } else {
8985 ALOGW("%s, input stream already closed", __func__);
8986 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008987 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308988 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008989 return;
8990}
8991
Aalique Grahame22e49102018-12-18 14:23:57 -08008992/* verifies input and output devices and their capabilities.
8993 *
8994 * This verification is required when enabling extended bit-depth or
8995 * sampling rates, as not all qcom products support it.
8996 *
8997 * Suitable for calling only on initialization such as adev_open().
8998 * It fills the audio_device use_case_table[] array.
8999 *
9000 * Has a side-effect that it needs to configure audio routing / devices
9001 * in order to power up the devices and read the device parameters.
9002 * It does not acquire any hw device lock. Should restore the devices
9003 * back to "normal state" upon completion.
9004 */
9005static int adev_verify_devices(struct audio_device *adev)
9006{
9007 /* enumeration is a bit difficult because one really wants to pull
9008 * the use_case, device id, etc from the hidden pcm_device_table[].
9009 * In this case there are the following use cases and device ids.
9010 *
9011 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
9012 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
9013 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
9014 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
9015 * [USECASE_AUDIO_RECORD] = {0, 0},
9016 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
9017 * [USECASE_VOICE_CALL] = {2, 2},
9018 *
9019 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
9020 * USECASE_VOICE_CALL omitted, but possible for either input or output.
9021 */
9022
9023 /* should be the usecases enabled in adev_open_input_stream() */
9024 static const int test_in_usecases[] = {
9025 USECASE_AUDIO_RECORD,
9026 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
9027 };
9028 /* should be the usecases enabled in adev_open_output_stream()*/
9029 static const int test_out_usecases[] = {
9030 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
9031 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
9032 };
9033 static const usecase_type_t usecase_type_by_dir[] = {
9034 PCM_PLAYBACK,
9035 PCM_CAPTURE,
9036 };
9037 static const unsigned flags_by_dir[] = {
9038 PCM_OUT,
9039 PCM_IN,
9040 };
9041
9042 size_t i;
9043 unsigned dir;
9044 const unsigned card_id = adev->snd_card;
9045
9046 for (dir = 0; dir < 2; ++dir) {
9047 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
9048 const unsigned flags_dir = flags_by_dir[dir];
9049 const size_t testsize =
9050 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
9051 const int *testcases =
9052 dir ? test_in_usecases : test_out_usecases;
9053 const audio_devices_t audio_device =
9054 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
9055
9056 for (i = 0; i < testsize; ++i) {
9057 const audio_usecase_t audio_usecase = testcases[i];
9058 int device_id;
9059 struct pcm_params **pparams;
9060 struct stream_out out;
9061 struct stream_in in;
9062 struct audio_usecase uc_info;
9063 int retval;
9064
9065 pparams = &adev->use_case_table[audio_usecase];
9066 pcm_params_free(*pparams); /* can accept null input */
9067 *pparams = NULL;
9068
9069 /* find the device ID for the use case (signed, for error) */
9070 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
9071 if (device_id < 0)
9072 continue;
9073
9074 /* prepare structures for device probing */
9075 memset(&uc_info, 0, sizeof(uc_info));
9076 uc_info.id = audio_usecase;
9077 uc_info.type = usecase_type;
9078 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08009079 memset(&in, 0, sizeof(in));
9080 in.device = audio_device;
9081 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
9082 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08009083 }
9084 memset(&out, 0, sizeof(out));
9085 out.devices = audio_device; /* only field needed in select_devices */
9086 uc_info.stream.out = &out;
9087 uc_info.devices = audio_device;
9088 uc_info.in_snd_device = SND_DEVICE_NONE;
9089 uc_info.out_snd_device = SND_DEVICE_NONE;
9090 list_add_tail(&adev->usecase_list, &uc_info.list);
9091
9092 /* select device - similar to start_(in/out)put_stream() */
9093 retval = select_devices(adev, audio_usecase);
9094 if (retval >= 0) {
9095 *pparams = pcm_params_get(card_id, device_id, flags_dir);
9096#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07009097 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08009098 if (*pparams) {
9099 ALOGV("%s: (%s) card %d device %d", __func__,
9100 dir ? "input" : "output", card_id, device_id);
9101 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
9102 } else {
9103 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
9104 }
9105#endif
9106 }
9107
9108 /* deselect device - similar to stop_(in/out)put_stream() */
9109 /* 1. Get and set stream specific mixer controls */
9110 retval = disable_audio_route(adev, &uc_info);
9111 /* 2. Disable the rx device */
9112 retval = disable_snd_device(adev,
9113 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
9114 list_remove(&uc_info.list);
9115 }
9116 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009117 return 0;
9118}
9119
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309120int adev_create_audio_patch(struct audio_hw_device *dev,
9121 unsigned int num_sources,
9122 const struct audio_port_config *sources,
9123 unsigned int num_sinks,
9124 const struct audio_port_config *sinks,
9125 audio_patch_handle_t *handle)
9126{
Derek Chenf939fb72018-11-13 13:34:41 -08009127 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309128
Derek Chenf939fb72018-11-13 13:34:41 -08009129 ret = audio_extn_hw_loopback_create_audio_patch(dev,
9130 num_sources,
9131 sources,
9132 num_sinks,
9133 sinks,
9134 handle);
9135 ret |= audio_extn_auto_hal_create_audio_patch(dev,
9136 num_sources,
9137 sources,
9138 num_sinks,
9139 sinks,
9140 handle);
9141 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309142}
9143
9144int adev_release_audio_patch(struct audio_hw_device *dev,
9145 audio_patch_handle_t handle)
9146{
Derek Chenf939fb72018-11-13 13:34:41 -08009147 int ret;
9148
9149 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
9150 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
9151 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309152}
9153
9154int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
9155{
Derek Chenf13dd492018-11-13 14:53:51 -08009156 int ret = 0;
9157
9158 ret = audio_extn_hw_loopback_get_audio_port(dev, config);
9159 ret |= audio_extn_auto_hal_get_audio_port(dev, config);
9160 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309161}
9162
9163int adev_set_audio_port_config(struct audio_hw_device *dev,
9164 const struct audio_port_config *config)
9165{
Derek Chenf13dd492018-11-13 14:53:51 -08009166 int ret = 0;
9167
9168 ret = audio_extn_hw_loopback_set_audio_port_config(dev, config);
9169 ret |= audio_extn_auto_hal_set_audio_port_config(dev, config);
9170 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309171}
9172
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07009173static int adev_dump(const audio_hw_device_t *device __unused,
9174 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009175{
9176 return 0;
9177}
9178
9179static int adev_close(hw_device_t *device)
9180{
Aalique Grahame22e49102018-12-18 14:23:57 -08009181 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009182 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07009183
9184 if (!adev)
9185 return 0;
9186
9187 pthread_mutex_lock(&adev_init_lock);
9188
9189 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05309190 if (audio_extn_spkr_prot_is_enabled())
9191 audio_extn_spkr_prot_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309192 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07009193 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08009194 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009195 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08009196 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309197 audio_extn_utils_release_streams_cfg_lists(
9198 &adev->streams_output_cfg_list,
9199 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309200 if (audio_extn_qaf_is_enabled())
9201 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009202 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08009203 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07009204 free(adev->snd_dev_ref_cnt);
9205 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009206 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
9207 pcm_params_free(adev->use_case_table[i]);
9208 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009209 if (adev->adm_deinit)
9210 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309211 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009212 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309213 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309214 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009215 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309216 if (adev->device_cfg_params) {
9217 free(adev->device_cfg_params);
9218 adev->device_cfg_params = NULL;
9219 }
Derek Chend2530072014-11-24 12:39:14 -08009220 if(adev->ext_hw_plugin)
9221 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08009222 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07009223 free(device);
9224 adev = NULL;
9225 }
9226 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05309227 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009228 return 0;
9229}
9230
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009231/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
9232 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
9233 * just that it _might_ work.
9234 */
9235static int period_size_is_plausible_for_low_latency(int period_size)
9236{
9237 switch (period_size) {
9238 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009239 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009240 case 240:
9241 case 320:
9242 case 480:
9243 return 1;
9244 default:
9245 return 0;
9246 }
9247}
9248
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309249static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9250{
9251 bool is_snd_card_status = false;
9252 bool is_ext_device_status = false;
9253 char value[32];
9254 int card = -1;
9255 card_status_t status;
9256
9257 if (cookie != adev || !parms)
9258 return;
9259
9260 if (!parse_snd_card_status(parms, &card, &status)) {
9261 is_snd_card_status = true;
9262 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9263 is_ext_device_status = true;
9264 } else {
9265 // not a valid event
9266 return;
9267 }
9268
9269 pthread_mutex_lock(&adev->lock);
9270 if (card == adev->snd_card || is_ext_device_status) {
9271 if (is_snd_card_status && adev->card_status != status) {
9272 adev->card_status = status;
9273 platform_snd_card_update(adev->platform, status);
9274 audio_extn_fm_set_parameters(adev, parms);
Derek Chend6f371d2019-03-01 13:45:58 -08009275 audio_extn_auto_hal_set_parameters(adev, parms);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309276 } else if (is_ext_device_status) {
9277 platform_set_parameters(adev->platform, parms);
9278 }
9279 }
9280 pthread_mutex_unlock(&adev->lock);
9281 return;
9282}
9283
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309284/* out and adev lock held */
9285static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9286{
9287 struct audio_usecase *uc_info;
9288 float left_p;
9289 float right_p;
9290 audio_devices_t devices;
9291
9292 uc_info = get_usecase_from_list(adev, out->usecase);
9293 if (uc_info == NULL) {
9294 ALOGE("%s: Could not find the usecase (%d) in the list",
9295 __func__, out->usecase);
9296 return -EINVAL;
9297 }
9298
9299 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9300 out->usecase, use_case_table[out->usecase]);
9301
9302 if (restore) {
9303 // restore A2DP device for active usecases and unmute if required
9304 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9305 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9306 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9307 select_devices(adev, uc_info->id);
9308 pthread_mutex_lock(&out->compr_mute_lock);
9309 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9310 (out->a2dp_compress_mute)) {
9311 out->a2dp_compress_mute = false;
9312 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9313 }
9314 pthread_mutex_unlock(&out->compr_mute_lock);
9315 }
9316 } else {
9317 // mute compress stream if suspended
9318 pthread_mutex_lock(&out->compr_mute_lock);
9319 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9320 (!out->a2dp_compress_mute)) {
9321 if (!out->standby) {
9322 ALOGD("%s: selecting speaker and muting stream", __func__);
9323 devices = out->devices;
9324 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9325 left_p = out->volume_l;
9326 right_p = out->volume_r;
9327 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9328 compress_pause(out->compr);
9329 out_set_compr_volume(&out->stream, (float)0, (float)0);
9330 out->a2dp_compress_mute = true;
9331 select_devices(adev, out->usecase);
9332 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9333 compress_resume(out->compr);
9334 out->devices = devices;
9335 out->volume_l = left_p;
9336 out->volume_r = right_p;
9337 }
9338 }
9339 pthread_mutex_unlock(&out->compr_mute_lock);
9340 }
9341 ALOGV("%s: exit", __func__);
9342 return 0;
9343}
9344
9345int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9346{
9347 int ret = 0;
9348
9349 lock_output_stream(out);
9350 pthread_mutex_lock(&adev->lock);
9351
9352 ret = check_a2dp_restore_l(adev, out, restore);
9353
9354 pthread_mutex_unlock(&adev->lock);
9355 pthread_mutex_unlock(&out->lock);
9356 return ret;
9357}
9358
Haynes Mathew George01156f92018-04-13 15:29:54 -07009359void adev_on_battery_status_changed(bool charging)
9360{
9361 pthread_mutex_lock(&adev->lock);
9362 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9363 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009364 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009365 pthread_mutex_unlock(&adev->lock);
9366}
9367
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009368static int adev_open(const hw_module_t *module, const char *name,
9369 hw_device_t **device)
9370{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309371 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009372 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309373 char mixer_ctl_name[128] = {0};
9374 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309375
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009376 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009377 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9378
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009379 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009380 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009381 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009382 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009383 ALOGD("%s: returning existing instance of adev", __func__);
9384 ALOGD("%s: exit", __func__);
9385 pthread_mutex_unlock(&adev_init_lock);
9386 return 0;
9387 }
9388
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009389 adev = calloc(1, sizeof(struct audio_device));
9390
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009391 if (!adev) {
9392 pthread_mutex_unlock(&adev_init_lock);
9393 return -ENOMEM;
9394 }
9395
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009396 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9397
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009398 // register audio ext hidl at the earliest
9399 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309400#ifdef DYNAMIC_LOG_ENABLED
9401 register_for_dynamic_logging("hal");
9402#endif
9403
Derek Chenf939fb72018-11-13 13:34:41 -08009404 /* default audio HAL major version */
9405 uint32_t maj_version = 2;
9406 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9407 maj_version = atoi(value);
9408
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009409 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009410 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009411 adev->device.common.module = (struct hw_module_t *)module;
9412 adev->device.common.close = adev_close;
9413
9414 adev->device.init_check = adev_init_check;
9415 adev->device.set_voice_volume = adev_set_voice_volume;
9416 adev->device.set_master_volume = adev_set_master_volume;
9417 adev->device.get_master_volume = adev_get_master_volume;
9418 adev->device.set_master_mute = adev_set_master_mute;
9419 adev->device.get_master_mute = adev_get_master_mute;
9420 adev->device.set_mode = adev_set_mode;
9421 adev->device.set_mic_mute = adev_set_mic_mute;
9422 adev->device.get_mic_mute = adev_get_mic_mute;
9423 adev->device.set_parameters = adev_set_parameters;
9424 adev->device.get_parameters = adev_get_parameters;
9425 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9426 adev->device.open_output_stream = adev_open_output_stream;
9427 adev->device.close_output_stream = adev_close_output_stream;
9428 adev->device.open_input_stream = adev_open_input_stream;
9429 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309430 adev->device.create_audio_patch = adev_create_audio_patch;
9431 adev->device.release_audio_patch = adev_release_audio_patch;
9432 adev->device.get_audio_port = adev_get_audio_port;
9433 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009434 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309435 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009436
9437 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009438 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009439 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009440 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009441 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009442 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009443 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309444 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009445 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009446 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009447 /* Init audio and voice feature */
9448 audio_extn_feature_init();
9449 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009450 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009451 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009452 list_init(&adev->active_inputs_list);
9453 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009454 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009455 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309456 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309457 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309458 adev->perf_lock_opts[0] = 0x101;
9459 adev->perf_lock_opts[1] = 0x20E;
9460 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009461 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009462 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309463 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009464 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309465
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009466 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009467 adev->platform = platform_init(adev);
9468 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009469 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009470 free(adev->snd_dev_ref_cnt);
9471 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009472 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009473 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9474 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009475 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009476 return -EINVAL;
9477 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009478
Aalique Grahame22e49102018-12-18 14:23:57 -08009479 adev->extspk = audio_extn_extspk_init(adev);
9480
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309481 if (audio_extn_qaf_is_enabled()) {
9482 ret = audio_extn_qaf_init(adev);
9483 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009484 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309485 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009486 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309487 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9488 *device = NULL;
9489 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309490 return ret;
9491 }
9492
9493 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9494 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9495 }
9496
Derek Chenae7b0342019-02-08 15:17:04 -08009497 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009498 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9499
Eric Laurentc4aef752013-09-12 17:45:53 -07009500 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9501 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9502 if (adev->visualizer_lib == NULL) {
9503 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9504 } else {
9505 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9506 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009507 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009508 "visualizer_hal_start_output");
9509 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009510 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009511 "visualizer_hal_stop_output");
9512 }
9513 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309514 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009515 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009516 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009517 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309518 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009519 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009520
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009521 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9522 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9523 if (adev->offload_effects_lib == NULL) {
9524 ALOGE("%s: DLOPEN failed for %s", __func__,
9525 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9526 } else {
9527 ALOGV("%s: DLOPEN successful for %s", __func__,
9528 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9529 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309530 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009531 "offload_effects_bundle_hal_start_output");
9532 adev->offload_effects_stop_output =
9533 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9534 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009535 adev->offload_effects_set_hpx_state =
9536 (int (*)(bool))dlsym(adev->offload_effects_lib,
9537 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309538 adev->offload_effects_get_parameters =
9539 (void (*)(struct str_parms *, struct str_parms *))
9540 dlsym(adev->offload_effects_lib,
9541 "offload_effects_bundle_get_parameters");
9542 adev->offload_effects_set_parameters =
9543 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9544 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009545 }
9546 }
9547
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009548 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9549 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9550 if (adev->adm_lib == NULL) {
9551 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9552 } else {
9553 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9554 adev->adm_init = (adm_init_t)
9555 dlsym(adev->adm_lib, "adm_init");
9556 adev->adm_deinit = (adm_deinit_t)
9557 dlsym(adev->adm_lib, "adm_deinit");
9558 adev->adm_register_input_stream = (adm_register_input_stream_t)
9559 dlsym(adev->adm_lib, "adm_register_input_stream");
9560 adev->adm_register_output_stream = (adm_register_output_stream_t)
9561 dlsym(adev->adm_lib, "adm_register_output_stream");
9562 adev->adm_deregister_stream = (adm_deregister_stream_t)
9563 dlsym(adev->adm_lib, "adm_deregister_stream");
9564 adev->adm_request_focus = (adm_request_focus_t)
9565 dlsym(adev->adm_lib, "adm_request_focus");
9566 adev->adm_abandon_focus = (adm_abandon_focus_t)
9567 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009568 adev->adm_set_config = (adm_set_config_t)
9569 dlsym(adev->adm_lib, "adm_set_config");
9570 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9571 dlsym(adev->adm_lib, "adm_request_focus_v2");
9572 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9573 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9574 adev->adm_on_routing_change = (adm_on_routing_change_t)
9575 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009576 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9577 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009578 }
9579 }
9580
Aalique Grahame22e49102018-12-18 14:23:57 -08009581 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009582 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009583 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009584 //initialize this to false for now,
9585 //this will be set to true through set param
9586 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009587
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009588 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009589 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009590
9591 if (k_enable_extended_precision)
9592 adev_verify_devices(adev);
9593
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009594 adev->dsp_bit_width_enforce_mode =
9595 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009596
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309597 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9598 &adev->streams_output_cfg_list,
9599 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009600
Kiran Kandi910e1862013-10-29 13:29:42 -07009601 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009602
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009603 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009604 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9605 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009606 trial = atoi(value);
9607 if (period_size_is_plausible_for_low_latency(trial)) {
9608 pcm_config_low_latency.period_size = trial;
9609 pcm_config_low_latency.start_threshold = trial / 4;
9610 pcm_config_low_latency.avail_min = trial / 4;
9611 configured_low_latency_capture_period_size = trial;
9612 }
9613 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009614 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9615 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009616 trial = atoi(value);
9617 if (period_size_is_plausible_for_low_latency(trial)) {
9618 configured_low_latency_capture_period_size = trial;
9619 }
9620 }
9621
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009622 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9623
Eric Laurent4b084132018-10-19 17:33:43 -07009624 adev->camera_orientation = CAMERA_DEFAULT;
9625
Aalique Grahame22e49102018-12-18 14:23:57 -08009626 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9627 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009628 af_period_multiplier = atoi(value);
9629 if (af_period_multiplier < 0)
9630 af_period_multiplier = 2;
9631 else if (af_period_multiplier > 4)
9632 af_period_multiplier = 4;
9633
9634 ALOGV("new period_multiplier = %d", af_period_multiplier);
9635 }
9636
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009637 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009638
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009639 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009640 pthread_mutex_unlock(&adev_init_lock);
9641
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009642 if (adev->adm_init)
9643 adev->adm_data = adev->adm_init();
9644
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309645 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309646 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009647 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309648
9649 audio_extn_snd_mon_init();
9650 pthread_mutex_lock(&adev->lock);
9651 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9652 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009653 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9654 /*
9655 * if the battery state callback happens before charging can be queried,
9656 * it will be guarded with the adev->lock held in the cb function and so
9657 * the callback value will reflect the latest state
9658 */
9659 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309660 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009661 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009662 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009663 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309664 /* Allocate memory for Device config params */
9665 adev->device_cfg_params = (struct audio_device_config_param*)
9666 calloc(platform_get_max_codec_backend(),
9667 sizeof(struct audio_device_config_param));
9668 if (adev->device_cfg_params == NULL)
9669 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309670
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309671 /*
9672 * Check if new PSPD matrix mixer control is supported. If not
9673 * supported, then set flag so that old mixer ctrl is sent while
9674 * sending pspd coefficients on older kernel version. Query mixer
9675 * control for default pcm id and channel value one.
9676 */
9677 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9678 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9679
9680 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9681 if (!ctl) {
9682 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9683 __func__, mixer_ctl_name);
9684 adev->use_old_pspd_mix_ctrl = true;
9685 }
9686
Eric Laurent994a6932013-07-17 11:51:42 -07009687 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009688 return 0;
9689}
9690
9691static struct hw_module_methods_t hal_module_methods = {
9692 .open = adev_open,
9693};
9694
9695struct audio_module HAL_MODULE_INFO_SYM = {
9696 .common = {
9697 .tag = HARDWARE_MODULE_TAG,
9698 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9699 .hal_api_version = HARDWARE_HAL_API_VERSION,
9700 .id = AUDIO_HARDWARE_MODULE_ID,
9701 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009702 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009703 .methods = &hal_module_methods,
9704 },
9705};