blob: 07d7bd2b64226717b293ec94947f006a6b7a5ec8 [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
403 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback"
Eric Laurentb23d5282013-05-14 15:27:20 -0700404};
405
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700406static const audio_usecase_t offload_usecases[] = {
407 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700408 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
409 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
410 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
411 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
412 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
413 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
414 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
415 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700416};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800417
Varun Balaraje49253e2017-07-06 19:48:56 +0530418static const audio_usecase_t interactive_usecases[] = {
419 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
420 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
421 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
422 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
423 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
424 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
426 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
427};
428
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800429#define STRING_TO_ENUM(string) { #string, string }
430
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800431struct string_to_enum {
432 const char *name;
433 uint32_t value;
434};
435
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700436static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800437 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800438 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
439 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
440 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700441 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800442 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800444 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700445 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
446 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
447 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
448 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
449 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
450 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
451 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
452 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
453 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
455 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800456};
457
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700458static const struct string_to_enum formats_name_to_enum_table[] = {
459 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
460 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
461 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700462 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
463 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
464 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700465 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800466 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
467 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700468 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800469};
470
471//list of all supported sample rates by HDMI specification.
472static const int out_hdmi_sample_rates[] = {
473 32000, 44100, 48000, 88200, 96000, 176400, 192000,
474};
475
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700476static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800477 STRING_TO_ENUM(32000),
478 STRING_TO_ENUM(44100),
479 STRING_TO_ENUM(48000),
480 STRING_TO_ENUM(88200),
481 STRING_TO_ENUM(96000),
482 STRING_TO_ENUM(176400),
483 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700484};
485
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700486static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700487static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700488static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700489//cache last MBDRC cal step level
490static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700491
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530492static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
493static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700494static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800495static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530496static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530497
Vatsal Buchac09ae062018-11-14 13:25:08 +0530498#ifdef AUDIO_FEATURE_ENABLED_GCOV
499extern void __gcov_flush();
500static void enable_gcov()
501{
502 __gcov_flush();
503}
504#else
505static void enable_gcov()
506{
507}
508#endif
509
justinweng20fb6d82019-02-21 18:49:00 -0700510static int in_set_microphone_direction(const struct audio_stream_in *stream,
511 audio_microphone_direction_t dir);
512static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
513
514
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700515static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
516 int flags __unused)
517{
518 int dir = 0;
519 switch (uc_id) {
520 case USECASE_AUDIO_RECORD_LOW_LATENCY:
521 dir = 1;
522 case USECASE_AUDIO_PLAYBACK_ULL:
523 break;
524 default:
525 return false;
526 }
527
528 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
529 PCM_PLAYBACK : PCM_CAPTURE);
530 if (adev->adm_is_noirq_avail)
531 return adev->adm_is_noirq_avail(adev->adm_data,
532 adev->snd_card, dev_id, dir);
533 return false;
534}
535
536static void register_out_stream(struct stream_out *out)
537{
538 struct audio_device *adev = out->dev;
539 if (is_offload_usecase(out->usecase) ||
540 !adev->adm_register_output_stream)
541 return;
542
543 // register stream first for backward compatibility
544 adev->adm_register_output_stream(adev->adm_data,
545 out->handle,
546 out->flags);
547
548 if (!adev->adm_set_config)
549 return;
550
551 if (out->realtime)
552 adev->adm_set_config(adev->adm_data,
553 out->handle,
554 out->pcm, &out->config);
555}
556
557static void register_in_stream(struct stream_in *in)
558{
559 struct audio_device *adev = in->dev;
560 if (!adev->adm_register_input_stream)
561 return;
562
563 adev->adm_register_input_stream(adev->adm_data,
564 in->capture_handle,
565 in->flags);
566
567 if (!adev->adm_set_config)
568 return;
569
570 if (in->realtime)
571 adev->adm_set_config(adev->adm_data,
572 in->capture_handle,
573 in->pcm,
574 &in->config);
575}
576
577static void request_out_focus(struct stream_out *out, long ns)
578{
579 struct audio_device *adev = out->dev;
580
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700581 if (adev->adm_request_focus_v2)
582 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
583 else if (adev->adm_request_focus)
584 adev->adm_request_focus(adev->adm_data, out->handle);
585}
586
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700587static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700588{
589 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700590 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700591
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700592 if (adev->adm_request_focus_v2_1)
593 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
594 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700595 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
596 else if (adev->adm_request_focus)
597 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700598
599 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700600}
601
602static void release_out_focus(struct stream_out *out)
603{
604 struct audio_device *adev = out->dev;
605
606 if (adev->adm_abandon_focus)
607 adev->adm_abandon_focus(adev->adm_data, out->handle);
608}
609
610static void release_in_focus(struct stream_in *in)
611{
612 struct audio_device *adev = in->dev;
613 if (adev->adm_abandon_focus)
614 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
615}
616
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530617static int parse_snd_card_status(struct str_parms *parms, int *card,
618 card_status_t *status)
619{
620 char value[32]={0};
621 char state[32]={0};
622
623 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
624 if (ret < 0)
625 return -1;
626
627 // sscanf should be okay as value is of max length 32.
628 // same as sizeof state.
629 if (sscanf(value, "%d,%s", card, state) < 2)
630 return -1;
631
632 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
633 CARD_STATUS_OFFLINE;
634 return 0;
635}
636
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700637static inline void adjust_frames_for_device_delay(struct stream_out *out,
638 uint32_t *dsp_frames) {
639 // Adjustment accounts for A2dp encoder latency with offload usecases
640 // Note: Encoder latency is returned in ms.
641 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
642 unsigned long offset =
643 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
644 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
645 }
646}
647
vivek mehtaa76401a2015-04-24 14:12:15 -0700648__attribute__ ((visibility ("default")))
649bool audio_hw_send_gain_dep_calibration(int level) {
650 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700651 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700652
653 pthread_mutex_lock(&adev_init_lock);
654
655 if (adev != NULL && adev->platform != NULL) {
656 pthread_mutex_lock(&adev->lock);
657 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700658
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530659 // cache level info for any of the use case which
660 // was not started.
661 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700662
vivek mehtaa76401a2015-04-24 14:12:15 -0700663 pthread_mutex_unlock(&adev->lock);
664 } else {
665 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
666 }
667
668 pthread_mutex_unlock(&adev_init_lock);
669
670 return ret_val;
671}
672
Ashish Jain5106d362016-05-11 19:23:33 +0530673static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
674{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800675 bool gapless_enabled = false;
676 const char *mixer_ctl_name = "Compress Gapless Playback";
677 struct mixer_ctl *ctl;
678
679 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700680 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530681
682 /*Disable gapless if its AV playback*/
683 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800684
685 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
686 if (!ctl) {
687 ALOGE("%s: Could not get ctl for mixer cmd - %s",
688 __func__, mixer_ctl_name);
689 return -EINVAL;
690 }
691
692 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
693 ALOGE("%s: Could not set gapless mode %d",
694 __func__, gapless_enabled);
695 return -EINVAL;
696 }
697 return 0;
698}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700699
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700700__attribute__ ((visibility ("default")))
701int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
702 int table_size) {
703 int ret_val = 0;
704 ALOGV("%s: enter ... ", __func__);
705
706 pthread_mutex_lock(&adev_init_lock);
707 if (adev == NULL) {
708 ALOGW("%s: adev is NULL .... ", __func__);
709 goto done;
710 }
711
712 pthread_mutex_lock(&adev->lock);
713 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
714 pthread_mutex_unlock(&adev->lock);
715done:
716 pthread_mutex_unlock(&adev_init_lock);
717 ALOGV("%s: exit ... ", __func__);
718 return ret_val;
719}
720
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800721bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800722{
723 bool ret = false;
724 ALOGV("%s: enter ...", __func__);
725
726 pthread_mutex_lock(&adev_init_lock);
727
728 if (adev != NULL && adev->platform != NULL) {
729 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800730 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800731 pthread_mutex_unlock(&adev->lock);
732 }
733
734 pthread_mutex_unlock(&adev_init_lock);
735
736 ALOGV("%s: exit with ret %d", __func__, ret);
737 return ret;
738}
Aalique Grahame22e49102018-12-18 14:23:57 -0800739
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700740static bool is_supported_format(audio_format_t format)
741{
Eric Laurent86e17132013-09-12 17:49:30 -0700742 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530743 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530744 format == AUDIO_FORMAT_AAC_LC ||
745 format == AUDIO_FORMAT_AAC_HE_V1 ||
746 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530747 format == AUDIO_FORMAT_AAC_ADTS_LC ||
748 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
749 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530750 format == AUDIO_FORMAT_AAC_LATM_LC ||
751 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
752 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530753 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
754 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530755 format == AUDIO_FORMAT_PCM_FLOAT ||
756 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700757 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530758 format == AUDIO_FORMAT_AC3 ||
759 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700760 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530761 format == AUDIO_FORMAT_DTS ||
762 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800763 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530764 format == AUDIO_FORMAT_ALAC ||
765 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530766 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530767 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800768 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530769 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700770 format == AUDIO_FORMAT_APTX ||
771 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800772 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700773
774 return false;
775}
776
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700777static inline bool is_mmap_usecase(audio_usecase_t uc_id)
778{
779 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
780 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
781}
782
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -0700783static inline bool is_valid_volume(float left, float right)
784{
785 return ((left >= 0.0f && right >= 0.0f) ? true : false);
786}
787
Avinash Vaish71a8b972014-07-24 15:36:33 +0530788static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
789 struct audio_usecase *uc_info)
790{
791 struct listnode *node;
792 struct audio_usecase *usecase;
793
794 if (uc_info == NULL)
795 return -EINVAL;
796
797 /* Re-route all voice usecases on the shared backend other than the
798 specified usecase to new snd devices */
799 list_for_each(node, &adev->usecase_list) {
800 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800801 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530802 enable_audio_route(adev, usecase);
803 }
804 return 0;
805}
806
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530807static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530808{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530809 ALOGV("%s", __func__);
810 audio_route_apply_and_update_path(adev->audio_route,
811 "asrc-mode");
812 adev->asrc_mode_enabled = true;
813}
814
815static void disable_asrc_mode(struct audio_device *adev)
816{
817 ALOGV("%s", __func__);
818 audio_route_reset_and_update_path(adev->audio_route,
819 "asrc-mode");
820 adev->asrc_mode_enabled = false;
821}
822
823/*
824 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
825 * 44.1 or Native DSD backends are enabled for any of current use case.
826 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
827 * - Disable current mix path use case(Headphone backend) and re-enable it with
828 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
829 * e.g. Naitve DSD or Headphone 44.1 -> + 48
830 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530831static void check_and_set_asrc_mode(struct audio_device *adev,
832 struct audio_usecase *uc_info,
833 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530834{
835 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530836 int i, num_new_devices = 0;
837 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
838 /*
839 *Split snd device for new combo use case
840 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
841 */
842 if (platform_split_snd_device(adev->platform,
843 snd_device,
844 &num_new_devices,
845 split_new_snd_devices) == 0) {
846 for (i = 0; i < num_new_devices; i++)
847 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
848 } else {
849 int new_backend_idx = platform_get_backend_index(snd_device);
850 if (((new_backend_idx == HEADPHONE_BACKEND) ||
851 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
852 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
853 !adev->asrc_mode_enabled) {
854 struct listnode *node = NULL;
855 struct audio_usecase *uc = NULL;
856 struct stream_out *curr_out = NULL;
857 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
858 int i, num_devices, ret = 0;
859 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530860
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530861 list_for_each(node, &adev->usecase_list) {
862 uc = node_to_item(node, struct audio_usecase, list);
863 curr_out = (struct stream_out*) uc->stream.out;
864 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
865 /*
866 *Split snd device for existing combo use case
867 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
868 */
869 ret = platform_split_snd_device(adev->platform,
870 uc->out_snd_device,
871 &num_devices,
872 split_snd_devices);
873 if (ret < 0 || num_devices == 0) {
874 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
875 split_snd_devices[0] = uc->out_snd_device;
876 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800877 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530878 for (i = 0; i < num_devices; i++) {
879 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
880 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
881 if((new_backend_idx == HEADPHONE_BACKEND) &&
882 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
883 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
884 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
885 __func__);
886 enable_asrc_mode(adev);
887 break;
888 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
889 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
890 (usecase_backend_idx == HEADPHONE_BACKEND)) {
891 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
892 __func__);
893 disable_audio_route(adev, uc);
894 disable_snd_device(adev, uc->out_snd_device);
895 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
896 if (new_backend_idx == DSD_NATIVE_BACKEND)
897 audio_route_apply_and_update_path(adev->audio_route,
898 "hph-true-highquality-mode");
899 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
900 (curr_out->bit_width >= 24))
901 audio_route_apply_and_update_path(adev->audio_route,
902 "hph-highquality-mode");
903 enable_asrc_mode(adev);
904 enable_snd_device(adev, uc->out_snd_device);
905 enable_audio_route(adev, uc);
906 break;
907 }
908 }
909 // reset split devices count
910 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800911 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530912 if (adev->asrc_mode_enabled)
913 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530914 }
915 }
916 }
917}
918
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700919static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
920 struct audio_effect_config effect_config,
921 unsigned int param_value)
922{
923 char mixer_ctl_name[] = "Audio Effect";
924 struct mixer_ctl *ctl;
925 long set_values[6];
Eric Laurent637e2d42018-11-15 12:24:31 -0800926 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700927
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700928 if (in == NULL) {
929 ALOGE("%s: active input stream is NULL", __func__);
930 return -EINVAL;
931 }
932
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700933 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
934 if (!ctl) {
935 ALOGE("%s: Could not get mixer ctl - %s",
936 __func__, mixer_ctl_name);
937 return -EINVAL;
938 }
939
940 set_values[0] = 1; //0:Rx 1:Tx
941 set_values[1] = in->app_type_cfg.app_type;
942 set_values[2] = (long)effect_config.module_id;
943 set_values[3] = (long)effect_config.instance_id;
944 set_values[4] = (long)effect_config.param_id;
945 set_values[5] = param_value;
946
947 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
948
949 return 0;
950
951}
952
953static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
954 int effect_type, unsigned int *param_value)
955{
956 int ret = 0;
957 struct audio_effect_config other_effect_config;
958 struct audio_usecase *usecase = NULL;
Eric Laurent637e2d42018-11-15 12:24:31 -0800959 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700960
Aniket Kumar Lata7de63522019-06-13 11:05:18 -0700961 if (in == NULL) {
962 ALOGE("%s: active input stream is NULL", __func__);
963 return -EINVAL;
964 }
965
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700966 usecase = get_usecase_from_list(adev, in->usecase);
967 if (!usecase)
968 return -EINVAL;
969
970 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
971 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
972 if (ret < 0) {
973 ALOGE("%s Failed to get effect params %d", __func__, ret);
974 return ret;
975 }
976
977 if (module_id == other_effect_config.module_id) {
978 //Same module id for AEC/NS. Values need to be combined
979 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
980 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
981 *param_value |= other_effect_config.param_value;
982 }
983 }
984
985 return ret;
986}
987
988static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +0530989{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700990 struct audio_effect_config effect_config;
991 struct audio_usecase *usecase = NULL;
992 int ret = 0;
993 unsigned int param_value = 0;
Eric Laurent637e2d42018-11-15 12:24:31 -0800994 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700995
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800996 if(!voice_extn_is_dynamic_ecns_enabled())
997 return ENOSYS;
998
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700999 if (!in) {
1000 ALOGE("%s: Invalid input stream", __func__);
1001 return -EINVAL;
1002 }
1003
1004 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
1005
1006 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +08001007 if (usecase == NULL) {
1008 ALOGE("%s: Could not find the usecase (%d) in the list",
1009 __func__, in->usecase);
1010 return -EINVAL;
1011 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001012
1013 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1014 if (ret < 0) {
1015 ALOGE("%s Failed to get module id %d", __func__, ret);
1016 return ret;
1017 }
1018 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1019 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1020
1021 if(enable)
1022 param_value = effect_config.param_value;
1023
1024 /*Special handling for AEC & NS effects Param values need to be
1025 updated if module ids are same*/
1026
1027 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1028 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1029 if (ret < 0)
1030 return ret;
1031 }
1032
1033 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1034
1035 return ret;
1036}
1037
1038static void check_and_enable_effect(struct audio_device *adev)
1039{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001040 if(!voice_extn_is_dynamic_ecns_enabled())
1041 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001042
Eric Laurent637e2d42018-11-15 12:24:31 -08001043 struct stream_in *in = adev_get_active_input(adev);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001044
Eric Laurent637e2d42018-11-15 12:24:31 -08001045 if (in != NULL && !in->standby) {
1046 if (in->enable_aec)
1047 enable_disable_effect(adev, EFFECT_AEC, true);
1048
1049 if (in->enable_ns &&
1050 in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1051 enable_disable_effect(adev, EFFECT_NS, true);
1052 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001053 }
1054}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001055
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001056int pcm_ioctl(struct pcm *pcm, int request, ...)
1057{
1058 va_list ap;
1059 void * arg;
1060 int pcm_fd = *(int*)pcm;
1061
1062 va_start(ap, request);
1063 arg = va_arg(ap, void *);
1064 va_end(ap);
1065
1066 return ioctl(pcm_fd, request, arg);
1067}
1068
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001069int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001070 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001071{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001072 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001073 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301074 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301075 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001076
1077 if (usecase == NULL)
1078 return -EINVAL;
1079
1080 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1081
Surendar Karka93cd25a2018-08-28 14:21:37 +05301082 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001083 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001084 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001085 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001086
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001087#ifdef DS1_DOLBY_DAP_ENABLED
1088 audio_extn_dolby_set_dmid(adev);
1089 audio_extn_dolby_set_endpoint(adev);
1090#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001091 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001092 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301093 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001094 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001095 if (audio_extn_is_maxx_audio_enabled())
1096 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301097 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301098 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1099 out = usecase->stream.out;
1100 if (out && out->compr)
1101 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1102 }
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301103 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301104
Andy Hung756ecc12018-10-19 17:47:12 -07001105 // we shouldn't truncate mixer_path
1106 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1107 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1108 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001109 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001110 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301111 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1112 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1113 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1114 if (parms) {
1115 audio_extn_fm_set_parameters(adev, parms);
1116 str_parms_destroy(parms);
1117 }
1118 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001119 ALOGV("%s: exit", __func__);
1120 return 0;
1121}
1122
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001123int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001124 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001125{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001126 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001127 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001128
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301129 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001130 return -EINVAL;
1131
1132 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301133 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134 snd_device = usecase->in_snd_device;
1135 else
1136 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001137 // we shouldn't truncate mixer_path
1138 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1139 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1140 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001141 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001142 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001143 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001144 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301145 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301146 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001147 if ((usecase->type == PCM_PLAYBACK) &&
1148 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301149 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001150 ALOGV("%s: exit", __func__);
1151 return 0;
1152}
1153
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001154int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001155 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001156{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301157 int i, num_devices = 0;
1158 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001159 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1160
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001161 if (snd_device < SND_DEVICE_MIN ||
1162 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001163 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001164 return -EINVAL;
1165 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001166
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001167 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001168 ALOGE("%s: Invalid sound device returned", __func__);
1169 return -EINVAL;
1170 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001171
1172 adev->snd_dev_ref_cnt[snd_device]++;
1173
1174 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1175 (platform_split_snd_device(adev->platform,
1176 snd_device,
1177 &num_devices,
1178 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001179 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001180 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001181 return 0;
1182 }
1183
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001184 if (audio_extn_spkr_prot_is_enabled())
1185 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001186
Aalique Grahame22e49102018-12-18 14:23:57 -08001187 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1188
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001189 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1190 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001191 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1192 goto err;
1193 }
1194 audio_extn_dev_arbi_acquire(snd_device);
1195 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001196 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001197 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001198 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001199 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001200 } else if (platform_split_snd_device(adev->platform,
1201 snd_device,
1202 &num_devices,
1203 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301204 for (i = 0; i < num_devices; i++) {
1205 enable_snd_device(adev, new_snd_devices[i]);
1206 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001207 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001208 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001209 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301210
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301211
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001212 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1213 (audio_extn_a2dp_start_playback() < 0)) {
1214 ALOGE(" fail to configure A2dp Source control path ");
1215 goto err;
1216 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001217
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001218 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1219 (audio_extn_a2dp_start_capture() < 0)) {
1220 ALOGE(" fail to configure A2dp Sink control path ");
1221 goto err;
1222 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301223
Zhou Song12c29502019-03-16 10:37:18 +08001224 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1225 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1226 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1227 (audio_extn_sco_start_configuration() < 0)) {
1228 ALOGE(" fail to configure sco control path ");
1229 goto err;
1230 }
1231
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001232 /* due to the possibility of calibration overwrite between listen
1233 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001234 audio_extn_sound_trigger_update_device_status(snd_device,
1235 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301236 audio_extn_listen_update_device_status(snd_device,
1237 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001238 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001239 audio_extn_sound_trigger_update_device_status(snd_device,
1240 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301241 audio_extn_listen_update_device_status(snd_device,
1242 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001243 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001244 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001245 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001246 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301247
1248 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1249 !adev->native_playback_enabled &&
1250 audio_is_true_native_stream_active(adev)) {
1251 ALOGD("%s: %d: napb: enabling native mode in hardware",
1252 __func__, __LINE__);
1253 audio_route_apply_and_update_path(adev->audio_route,
1254 "true-native-mode");
1255 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301256 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301257 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1258 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001259 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001260 ALOGD("%s: init ec ref loopback", __func__);
1261 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1262 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001263 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001264 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001265err:
1266 adev->snd_dev_ref_cnt[snd_device]--;
1267 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001268}
1269
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001270int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001271 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001272{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301273 int i, num_devices = 0;
1274 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001275 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1276
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001277 if (snd_device < SND_DEVICE_MIN ||
1278 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001279 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001280 return -EINVAL;
1281 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001282
1283 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1284 ALOGE("%s: Invalid sound device returned", __func__);
1285 return -EINVAL;
1286 }
1287
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001288 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1289 ALOGE("%s: device ref cnt is already 0", __func__);
1290 return -EINVAL;
1291 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001292
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001293 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001294
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001295
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001296 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001297 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301298
Aalique Grahame22e49102018-12-18 14:23:57 -08001299 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1300
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001301 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1302 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001303 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001304
1305 // when speaker device is disabled, reset swap.
1306 // will be renabled on usecase start
1307 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001308 } else if (platform_split_snd_device(adev->platform,
1309 snd_device,
1310 &num_devices,
1311 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301312 for (i = 0; i < num_devices; i++) {
1313 disable_snd_device(adev, new_snd_devices[i]);
1314 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001315 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001316 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001317 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001318 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001319
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001320 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301321 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001322 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001323 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001324 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001325 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301326 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001327 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301328 adev->native_playback_enabled) {
1329 ALOGD("%s: %d: napb: disabling native mode in hardware",
1330 __func__, __LINE__);
1331 audio_route_reset_and_update_path(adev->audio_route,
1332 "true-native-mode");
1333 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001334 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301335 adev->asrc_mode_enabled) {
1336 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301337 disable_asrc_mode(adev);
1338 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001339 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301340 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Eric Laurent637e2d42018-11-15 12:24:31 -08001341 (audio_extn_ffv_get_stream() == adev_get_active_input(adev))) {
Garmond Leunge2433c32017-09-28 21:51:22 -07001342 ALOGD("%s: deinit ec ref loopback", __func__);
1343 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1344 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001345
1346 audio_extn_utils_release_snd_device(snd_device);
1347 } else {
1348 if (platform_split_snd_device(adev->platform,
1349 snd_device,
1350 &num_devices,
1351 new_snd_devices) == 0) {
1352 for (i = 0; i < num_devices; i++) {
1353 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1354 }
1355 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001356 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001357
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001358 return 0;
1359}
1360
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001361/*
1362 legend:
1363 uc - existing usecase
1364 new_uc - new usecase
1365 d1, d11, d2 - SND_DEVICE enums
1366 a1, a2 - corresponding ANDROID device enums
1367 B1, B2 - backend strings
1368
1369case 1
1370 uc->dev d1 (a1) B1
1371 new_uc->dev d1 (a1), d2 (a2) B1, B2
1372
1373 resolution: disable and enable uc->dev on d1
1374
1375case 2
1376 uc->dev d1 (a1) B1
1377 new_uc->dev d11 (a1) B1
1378
1379 resolution: need to switch uc since d1 and d11 are related
1380 (e.g. speaker and voice-speaker)
1381 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1382
1383case 3
1384 uc->dev d1 (a1) B1
1385 new_uc->dev d2 (a2) B2
1386
1387 resolution: no need to switch uc
1388
1389case 4
1390 uc->dev d1 (a1) B1
1391 new_uc->dev d2 (a2) B1
1392
1393 resolution: disable enable uc-dev on d2 since backends match
1394 we cannot enable two streams on two different devices if they
1395 share the same backend. e.g. if offload is on speaker device using
1396 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1397 using the same backend, offload must also be switched to voice-handset.
1398
1399case 5
1400 uc->dev d1 (a1) B1
1401 new_uc->dev d1 (a1), d2 (a2) B1
1402
1403 resolution: disable enable uc-dev on d2 since backends match
1404 we cannot enable two streams on two different devices if they
1405 share the same backend.
1406
1407case 6
1408 uc->dev d1 (a1) B1
1409 new_uc->dev d2 (a1) B2
1410
1411 resolution: no need to switch
1412
1413case 7
1414 uc->dev d1 (a1), d2 (a2) B1, B2
1415 new_uc->dev d1 (a1) B1
1416
1417 resolution: no need to switch
1418
Zhou Song4ba65882018-07-09 14:48:07 +08001419case 8
1420 uc->dev d1 (a1) B1
1421 new_uc->dev d11 (a1), d2 (a2) B1, B2
1422 resolution: compared to case 1, for this case, d1 and d11 are related
1423 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001424*/
1425static snd_device_t derive_playback_snd_device(void * platform,
1426 struct audio_usecase *uc,
1427 struct audio_usecase *new_uc,
1428 snd_device_t new_snd_device)
1429{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301430 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001431
1432 snd_device_t d1 = uc->out_snd_device;
1433 snd_device_t d2 = new_snd_device;
1434
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301435 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301436 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301437 a1 = uc->stream.inout->out_config.devices;
1438 a2 = new_uc->stream.inout->out_config.devices;
1439 break;
1440 default :
1441 a1 = uc->stream.out->devices;
1442 a2 = new_uc->stream.out->devices;
1443 break;
1444 }
1445
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001446 // Treat as a special case when a1 and a2 are not disjoint
1447 if ((a1 != a2) && (a1 & a2)) {
1448 snd_device_t d3[2];
1449 int num_devices = 0;
1450 int ret = platform_split_snd_device(platform,
1451 popcount(a1) > 1 ? d1 : d2,
1452 &num_devices,
1453 d3);
1454 if (ret < 0) {
1455 if (ret != -ENOSYS) {
1456 ALOGW("%s failed to split snd_device %d",
1457 __func__,
1458 popcount(a1) > 1 ? d1 : d2);
1459 }
1460 goto end;
1461 }
1462
1463 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1464 // But if it does happen, we need to give priority to d2 if
1465 // the combo devices active on the existing usecase share a backend.
1466 // This is because we cannot have a usecase active on a combo device
1467 // and a new usecase requests one device in this combo pair.
1468 if (platform_check_backends_match(d3[0], d3[1])) {
1469 return d2; // case 5
1470 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001471 // check if d1 is related to any of d3's
1472 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001473 return d1; // case 1
1474 else
1475 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001476 }
1477 } else {
1478 if (platform_check_backends_match(d1, d2)) {
1479 return d2; // case 2, 4
1480 } else {
1481 return d1; // case 6, 3
1482 }
1483 }
1484
1485end:
1486 return d2; // return whatever was calculated before.
1487}
1488
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001489static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301490 struct audio_usecase *uc_info,
1491 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001492{
1493 struct listnode *node;
1494 struct audio_usecase *usecase;
1495 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301496 snd_device_t uc_derive_snd_device;
1497 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001498 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1499 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001500 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301501 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001502 /*
1503 * This function is to make sure that all the usecases that are active on
1504 * the hardware codec backend are always routed to any one device that is
1505 * handled by the hardware codec.
1506 * For example, if low-latency and deep-buffer usecases are currently active
1507 * on speaker and out_set_parameters(headset) is received on low-latency
1508 * output, then we have to make sure deep-buffer is also switched to headset,
1509 * because of the limitation that both the devices cannot be enabled
1510 * at the same time as they share the same backend.
1511 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001512 /*
1513 * This call is to check if we need to force routing for a particular stream
1514 * If there is a backend configuration change for the device when a
1515 * new stream starts, then ADM needs to be closed and re-opened with the new
1516 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001517 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001518 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001519 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1520 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301521 /* For a2dp device reconfigure all active sessions
1522 * with new AFE encoder format based on a2dp state
1523 */
1524 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1525 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1526 audio_extn_a2dp_is_force_device_switch()) {
1527 force_routing = true;
1528 force_restart_session = true;
1529 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301530 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1531
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001532 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001533 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001534 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1536 switch_device[i] = false;
1537
1538 list_for_each(node, &adev->usecase_list) {
1539 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001540
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301541 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1542 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301543 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301544 platform_get_snd_device_name(usecase->out_snd_device),
1545 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301546 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1547 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1548 usecase, uc_info, snd_device);
1549 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1550 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1551 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1552 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001553 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301554 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1555 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1556 ((force_restart_session) ||
1557 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301558 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1559 __func__, use_case_table[usecase->id],
1560 platform_get_snd_device_name(usecase->out_snd_device));
1561 disable_audio_route(adev, usecase);
1562 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301563 /* Enable existing usecase on derived playback device */
1564 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301565 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301566 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001567 }
1568 }
1569
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301570 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1571 num_uc_to_switch);
1572
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001573 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001574 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001575
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301576 /* Make sure the previous devices to be disabled first and then enable the
1577 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001578 list_for_each(node, &adev->usecase_list) {
1579 usecase = node_to_item(node, struct audio_usecase, list);
1580 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001581 /* Check if output sound device to be switched can be split and if any
1582 of the split devices match with derived sound device */
1583 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1584 &num_devices, split_snd_devices) == 0) {
1585 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1586 for (i = 0; i < num_devices; i++) {
1587 /* Disable devices that do not match with derived sound device */
1588 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1589 disable_snd_device(adev, split_snd_devices[i]);
1590 }
1591 } else {
1592 disable_snd_device(adev, usecase->out_snd_device);
1593 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001594 }
1595 }
1596
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001597 list_for_each(node, &adev->usecase_list) {
1598 usecase = node_to_item(node, struct audio_usecase, list);
1599 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001600 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1601 &num_devices, split_snd_devices) == 0) {
1602 /* Enable derived sound device only if it does not match with
1603 one of the split sound devices. This is because the matching
1604 sound device was not disabled */
1605 bool should_enable = true;
1606 for (i = 0; i < num_devices; i++) {
1607 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1608 should_enable = false;
1609 break;
1610 }
1611 }
1612 if (should_enable)
1613 enable_snd_device(adev, derive_snd_device[usecase->id]);
1614 } else {
1615 enable_snd_device(adev, derive_snd_device[usecase->id]);
1616 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001617 }
1618 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001619
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001620 /* Re-route all the usecases on the shared backend other than the
1621 specified usecase to new snd devices */
1622 list_for_each(node, &adev->usecase_list) {
1623 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301624 /* Update the out_snd_device only before enabling the audio route */
1625 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301626 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301627 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301628 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301629 use_case_table[usecase->id],
1630 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001631 /* Update voc calibration before enabling VoIP route */
1632 if (usecase->type == VOIP_CALL)
1633 status = platform_switch_voice_call_device_post(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08001634 usecase->out_snd_device,
1635 platform_get_input_snd_device(
1636 adev->platform, NULL,
1637 uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301638 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301639 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001640 out_set_voip_volume(&usecase->stream.out->stream,
1641 usecase->stream.out->volume_l,
1642 usecase->stream.out->volume_r);
1643 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301644 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001645 }
1646 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001647 }
1648}
1649
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301650static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001651 struct audio_usecase *uc_info,
1652 snd_device_t snd_device)
1653{
1654 struct listnode *node;
1655 struct audio_usecase *usecase;
1656 bool switch_device[AUDIO_USECASE_MAX];
1657 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301658 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001659 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001660
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301661 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1662 snd_device);
1663 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301664
1665 /*
1666 * Make sure out devices is checked against out codec backend device and
1667 * also in devices against in codec backend. Checking out device against in
1668 * codec backend or vice versa causes issues.
1669 */
1670 if (uc_info->type == PCM_CAPTURE)
1671 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001672 /*
1673 * This function is to make sure that all the active capture usecases
1674 * are always routed to the same input sound device.
1675 * For example, if audio-record and voice-call usecases are currently
1676 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1677 * is received for voice call then we have to make sure that audio-record
1678 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1679 * because of the limitation that two devices cannot be enabled
1680 * at the same time if they share the same backend.
1681 */
1682 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1683 switch_device[i] = false;
1684
1685 list_for_each(node, &adev->usecase_list) {
1686 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301687 /*
1688 * TODO: Enhance below condition to handle BT sco/USB multi recording
1689 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001690 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001691 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301692 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301693 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301694 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301695 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001696 ((uc_info->type == VOICE_CALL &&
1697 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1698 platform_check_backends_match(snd_device,\
1699 usecase->in_snd_device)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001700 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001701 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1702 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001703 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001704 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001705 switch_device[usecase->id] = true;
1706 num_uc_to_switch++;
1707 }
1708 }
1709
1710 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001711 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001712
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301713 /* Make sure the previous devices to be disabled first and then enable the
1714 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001715 list_for_each(node, &adev->usecase_list) {
1716 usecase = node_to_item(node, struct audio_usecase, list);
1717 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001718 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001719 }
1720 }
1721
1722 list_for_each(node, &adev->usecase_list) {
1723 usecase = node_to_item(node, struct audio_usecase, list);
1724 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001725 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001726 }
1727 }
1728
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001729 /* Re-route all the usecases on the shared backend other than the
1730 specified usecase to new snd devices */
1731 list_for_each(node, &adev->usecase_list) {
1732 usecase = node_to_item(node, struct audio_usecase, list);
1733 /* Update the in_snd_device only before enabling the audio route */
1734 if (switch_device[usecase->id] ) {
1735 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001736 if (usecase->type != VOICE_CALL) {
1737 /* Update voc calibration before enabling VoIP route */
1738 if (usecase->type == VOIP_CALL)
1739 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001740 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001741 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301742 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001743 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001744 }
1745 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001746 }
1747}
1748
Mingming Yin3a941d42016-02-17 18:08:05 -08001749static void reset_hdmi_sink_caps(struct stream_out *out) {
1750 int i = 0;
1751
1752 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1753 out->supported_channel_masks[i] = 0;
1754 }
1755 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1756 out->supported_formats[i] = 0;
1757 }
1758 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1759 out->supported_sample_rates[i] = 0;
1760 }
1761}
1762
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001763/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001764static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001765{
Mingming Yin3a941d42016-02-17 18:08:05 -08001766 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001767 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001768
Mingming Yin3a941d42016-02-17 18:08:05 -08001769 reset_hdmi_sink_caps(out);
1770
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001771 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001772 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001773 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001774 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001775 }
1776
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001778 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001779 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001780 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001781 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1782 case 6:
1783 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1784 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1785 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1786 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1787 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1788 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001789 break;
1790 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001791 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001792 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001793 break;
1794 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001795
1796 // check channel format caps
1797 i = 0;
1798 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1799 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1800 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1801 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1802 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1803 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1804 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1805 }
1806
Ben Romberger1aaaf862017-04-06 17:49:46 -07001807 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1808 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1809 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1810 }
1811
Mingming Yin3a941d42016-02-17 18:08:05 -08001812 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1813 ALOGV(":%s HDMI supports DTS format", __func__);
1814 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1815 }
1816
1817 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1818 ALOGV(":%s HDMI supports DTS HD format", __func__);
1819 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1820 }
1821
Naresh Tanniru928f0862017-04-07 16:44:23 -07001822 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1823 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1824 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1825 }
1826
Mingming Yin3a941d42016-02-17 18:08:05 -08001827
1828 // check sample rate caps
1829 i = 0;
1830 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1831 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1832 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1833 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1834 }
1835 }
1836
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001837 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001838}
1839
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001840static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1841 uint32_t *supported_sample_rates __unused,
1842 uint32_t max_rates __unused)
1843{
1844 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1845 supported_sample_rates,
1846 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301847 ssize_t i = 0;
1848
1849 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001850 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1851 supported_sample_rates[i]);
1852 }
1853 return count;
1854}
1855
1856static inline int read_usb_sup_channel_masks(bool is_playback,
1857 audio_channel_mask_t *supported_channel_masks,
1858 uint32_t max_masks)
1859{
1860 int channels = audio_extn_usb_get_max_channels(is_playback);
1861 int channel_count;
1862 uint32_t num_masks = 0;
1863 if (channels > MAX_HIFI_CHANNEL_COUNT)
1864 channels = MAX_HIFI_CHANNEL_COUNT;
1865
1866 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001867 // start from 2 channels as framework currently doesn't support mono.
1868 if (channels >= FCC_2) {
1869 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1870 }
1871 for (channel_count = FCC_2;
1872 channel_count <= channels && num_masks < max_masks;
1873 ++channel_count) {
1874 supported_channel_masks[num_masks++] =
1875 audio_channel_mask_for_index_assignment_from_count(channel_count);
1876 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001877 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001878 // For capture we report all supported channel masks from 1 channel up.
1879 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001880 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1881 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001882 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1883 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1884 if (channel_count <= FCC_2) {
1885 mask = audio_channel_in_mask_from_count(channel_count);
1886 supported_channel_masks[num_masks++] = mask;
1887 }
1888 const audio_channel_mask_t index_mask =
1889 audio_channel_mask_for_index_assignment_from_count(channel_count);
1890 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1891 supported_channel_masks[num_masks++] = index_mask;
1892 }
1893 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001894 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301895
vincenttewf51c94e2019-05-07 10:28:53 +08001896 for (size_t i = 0; i < num_masks; ++i) {
1897 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1898 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301899 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001900 return num_masks;
1901}
1902
1903static inline int read_usb_sup_formats(bool is_playback __unused,
1904 audio_format_t *supported_formats,
1905 uint32_t max_formats __unused)
1906{
1907 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1908 switch (bitwidth) {
1909 case 24:
1910 // XXX : usb.c returns 24 for s24 and s24_le?
1911 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1912 break;
1913 case 32:
1914 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1915 break;
1916 case 16:
1917 default :
1918 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1919 break;
1920 }
1921 ALOGV("%s: %s supported format %d", __func__,
1922 is_playback ? "P" : "C", bitwidth);
1923 return 1;
1924}
1925
1926static inline int read_usb_sup_params_and_compare(bool is_playback,
1927 audio_format_t *format,
1928 audio_format_t *supported_formats,
1929 uint32_t max_formats,
1930 audio_channel_mask_t *mask,
1931 audio_channel_mask_t *supported_channel_masks,
1932 uint32_t max_masks,
1933 uint32_t *rate,
1934 uint32_t *supported_sample_rates,
1935 uint32_t max_rates) {
1936 int ret = 0;
1937 int num_formats;
1938 int num_masks;
1939 int num_rates;
1940 int i;
1941
1942 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1943 max_formats);
1944 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1945 max_masks);
1946
1947 num_rates = read_usb_sup_sample_rates(is_playback,
1948 supported_sample_rates, max_rates);
1949
1950#define LUT(table, len, what, dflt) \
1951 for (i=0; i<len && (table[i] != what); i++); \
1952 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1953
1954 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1955 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1956 LUT(supported_sample_rates, num_rates, *rate, 0);
1957
1958#undef LUT
1959 return ret < 0 ? -EINVAL : 0; // HACK TBD
1960}
1961
Alexy Josephb1379942016-01-29 15:49:38 -08001962audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001963 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001964{
1965 struct audio_usecase *usecase;
1966 struct listnode *node;
1967
1968 list_for_each(node, &adev->usecase_list) {
1969 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001970 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001971 ALOGV("%s: usecase id %d", __func__, usecase->id);
1972 return usecase->id;
1973 }
1974 }
1975 return USECASE_INVALID;
1976}
1977
Alexy Josephb1379942016-01-29 15:49:38 -08001978struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001979 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001980{
1981 struct audio_usecase *usecase;
1982 struct listnode *node;
1983
1984 list_for_each(node, &adev->usecase_list) {
1985 usecase = node_to_item(node, struct audio_usecase, list);
1986 if (usecase->id == uc_id)
1987 return usecase;
1988 }
1989 return NULL;
1990}
1991
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301992/*
1993 * is a true native playback active
1994 */
1995bool audio_is_true_native_stream_active(struct audio_device *adev)
1996{
1997 bool active = false;
1998 int i = 0;
1999 struct listnode *node;
2000
2001 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
2002 ALOGV("%s:napb: not in true mode or non hdphones device",
2003 __func__);
2004 active = false;
2005 goto exit;
2006 }
2007
2008 list_for_each(node, &adev->usecase_list) {
2009 struct audio_usecase *uc;
2010 uc = node_to_item(node, struct audio_usecase, list);
2011 struct stream_out *curr_out =
2012 (struct stream_out*) uc->stream.out;
2013
2014 if (curr_out && PCM_PLAYBACK == uc->type) {
2015 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2016 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2017 uc->id, curr_out->sample_rate,
2018 curr_out->bit_width,
2019 platform_get_snd_device_name(uc->out_snd_device));
2020
2021 if (is_offload_usecase(uc->id) &&
2022 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2023 active = true;
2024 ALOGD("%s:napb:native stream detected", __func__);
2025 }
2026 }
2027 }
2028exit:
2029 return active;
2030}
2031
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002032uint32_t adev_get_dsp_bit_width_enforce_mode()
2033{
2034 if (adev == NULL) {
2035 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2036 return 0;
2037 }
2038 return adev->dsp_bit_width_enforce_mode;
2039}
2040
2041static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2042{
2043 char value[PROPERTY_VALUE_MAX];
2044 int trial;
2045 uint32_t dsp_bit_width_enforce_mode = 0;
2046
2047 if (!mixer) {
2048 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2049 __func__);
2050 return 0;
2051 }
2052
2053 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2054 value, NULL) > 0) {
2055 trial = atoi(value);
2056 switch (trial) {
2057 case 16:
2058 dsp_bit_width_enforce_mode = 16;
2059 break;
2060 case 24:
2061 dsp_bit_width_enforce_mode = 24;
2062 break;
2063 case 32:
2064 dsp_bit_width_enforce_mode = 32;
2065 break;
2066 default:
2067 dsp_bit_width_enforce_mode = 0;
2068 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2069 break;
2070 }
2071 }
2072
2073 return dsp_bit_width_enforce_mode;
2074}
2075
2076static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2077 uint32_t enforce_mode,
2078 bool enable)
2079{
2080 struct mixer_ctl *ctl = NULL;
2081 const char *mixer_ctl_name = "ASM Bit Width";
2082 uint32_t asm_bit_width_mode = 0;
2083
2084 if (enforce_mode == 0) {
2085 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2086 return;
2087 }
2088
2089 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2090 if (!ctl) {
2091 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2092 __func__, mixer_ctl_name);
2093 return;
2094 }
2095
2096 if (enable)
2097 asm_bit_width_mode = enforce_mode;
2098 else
2099 asm_bit_width_mode = 0;
2100
2101 ALOGV("%s DSP bit width feature status is %d width=%d",
2102 __func__, enable, asm_bit_width_mode);
2103 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2104 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2105 asm_bit_width_mode);
2106
2107 return;
2108}
2109
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302110/*
2111 * if native DSD playback active
2112 */
2113bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2114{
2115 bool active = false;
2116 struct listnode *node = NULL;
2117 struct audio_usecase *uc = NULL;
2118 struct stream_out *curr_out = NULL;
2119
2120 list_for_each(node, &adev->usecase_list) {
2121 uc = node_to_item(node, struct audio_usecase, list);
2122 curr_out = (struct stream_out*) uc->stream.out;
2123
2124 if (curr_out && PCM_PLAYBACK == uc->type &&
2125 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2126 active = true;
2127 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302128 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302129 }
2130 }
2131 return active;
2132}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302133
2134static bool force_device_switch(struct audio_usecase *usecase)
2135{
2136 bool ret = false;
2137 bool is_it_true_mode = false;
2138
Zhou Song30f2c3e2018-02-08 14:02:15 +08002139 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302140 usecase->type == TRANSCODE_LOOPBACK_RX ||
2141 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002142 return false;
2143 }
2144
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002145 if(usecase->stream.out == NULL) {
2146 ALOGE("%s: stream.out is NULL", __func__);
2147 return false;
2148 }
2149
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302150 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002151 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2152 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2153 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302154 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2155 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2156 (!is_it_true_mode && adev->native_playback_enabled)){
2157 ret = true;
2158 ALOGD("napb: time to toggle native mode");
2159 }
2160 }
2161
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302162 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302163 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2164 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002165 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302166 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302167 ALOGD("Force a2dp device switch to update new encoder config");
2168 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002169 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302170
Florian Pfister1a84f312018-07-19 14:38:18 +02002171 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302172 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2173 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002174 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302175 return ret;
2176}
2177
Aalique Grahame22e49102018-12-18 14:23:57 -08002178static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2179{
2180 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2181}
2182
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302183bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2184{
2185 bool ret=false;
2186 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2187 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2188 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2189 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2190 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2191 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2192 ret = true;
2193
2194 return ret;
2195}
2196
2197bool is_a2dp_device(snd_device_t out_snd_device)
2198{
2199 bool ret=false;
2200 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2201 ret = true;
2202
2203 return ret;
2204}
2205
2206bool is_bt_soc_on(struct audio_device *adev)
2207{
2208 struct mixer_ctl *ctl;
2209 char *mixer_ctl_name = "BT SOC status";
2210 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2211 bool bt_soc_status = true;
2212 if (!ctl) {
2213 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2214 __func__, mixer_ctl_name);
2215 /*This is to ensure we dont break targets which dont have the kernel change*/
2216 return true;
2217 }
2218 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2219 ALOGD("BT SOC status: %d",bt_soc_status);
2220 return bt_soc_status;
2221}
2222
2223int out_standby_l(struct audio_stream *stream);
2224
Eric Laurent637e2d42018-11-15 12:24:31 -08002225struct stream_in *adev_get_active_input(const struct audio_device *adev)
2226{
2227 struct listnode *node;
2228 struct stream_in *last_active_in = NULL;
2229
2230 /* Get last added active input.
2231 * TODO: We may use a priority mechanism to pick highest priority active source */
2232 list_for_each(node, &adev->usecase_list)
2233 {
2234 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2235 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL)
2236 last_active_in = usecase->stream.in;
2237 }
2238
2239 return last_active_in;
2240}
2241
2242struct stream_in *get_voice_communication_input(const struct audio_device *adev)
2243{
2244 struct listnode *node;
2245
2246 /* First check active inputs with voice communication source and then
2247 * any input if audio mode is in communication */
2248 list_for_each(node, &adev->usecase_list)
2249 {
2250 struct audio_usecase *usecase = node_to_item(node, struct audio_usecase, list);
2251 if (usecase->type == PCM_CAPTURE && usecase->stream.in != NULL &&
2252 usecase->stream.in->source == AUDIO_SOURCE_VOICE_COMMUNICATION)
2253 return usecase->stream.in;
2254 }
2255 if (adev->mode == AUDIO_MODE_IN_COMMUNICATION)
2256 return adev_get_active_input(adev);
2257
2258 return NULL;
2259}
2260
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002261int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002262{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002263 snd_device_t out_snd_device = SND_DEVICE_NONE;
2264 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002265 struct audio_usecase *usecase = NULL;
2266 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002267 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002268 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302269 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002270 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002271 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002272
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302273 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2274
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002275 usecase = get_usecase_from_list(adev, uc_id);
2276 if (usecase == NULL) {
2277 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2278 return -EINVAL;
2279 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002280
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002281 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002282 (usecase->type == VOIP_CALL) ||
2283 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302284 if(usecase->stream.out == NULL) {
2285 ALOGE("%s: stream.out is NULL", __func__);
2286 return -EINVAL;
2287 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002288 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002289 usecase->stream.out);
Eric Laurent637e2d42018-11-15 12:24:31 -08002290 in_snd_device = platform_get_input_snd_device(adev->platform,
2291 NULL,
2292 usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002293 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302294 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302295 if (usecase->stream.inout == NULL) {
2296 ALOGE("%s: stream.inout is NULL", __func__);
2297 return -EINVAL;
2298 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302299 stream_out.devices = usecase->stream.inout->out_config.devices;
2300 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2301 stream_out.format = usecase->stream.inout->out_config.format;
2302 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2303 out_snd_device = platform_get_output_snd_device(adev->platform,
2304 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302305 usecase->devices = out_snd_device;
2306 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2307 if (usecase->stream.inout == NULL) {
2308 ALOGE("%s: stream.inout is NULL", __func__);
2309 return -EINVAL;
2310 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002311 in_snd_device = platform_get_input_snd_device(adev->platform, NULL, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302312 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002313 } else {
2314 /*
2315 * If the voice call is active, use the sound devices of voice call usecase
2316 * so that it would not result any device switch. All the usecases will
2317 * be switched to new device when select_devices() is called for voice call
2318 * usecase. This is to avoid switching devices for voice call when
2319 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002320 * choose voice call device only if the use case device is
2321 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002322 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002323 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002324 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002325 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002326 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2327 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302328 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2329 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002330 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2331 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002332 in_snd_device = vc_usecase->in_snd_device;
2333 out_snd_device = vc_usecase->out_snd_device;
2334 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002335 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002336 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002337 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002338 if ((voip_usecase != NULL) &&
2339 (usecase->type == PCM_PLAYBACK) &&
2340 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002341 out_snd_device_backend_match = platform_check_backends_match(
2342 voip_usecase->out_snd_device,
2343 platform_get_output_snd_device(
2344 adev->platform,
2345 usecase->stream.out));
2346 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002347 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002348 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2349 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002350 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002351 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002352 in_snd_device = voip_usecase->in_snd_device;
2353 out_snd_device = voip_usecase->out_snd_device;
2354 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002355 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002356 hfp_ucid = audio_extn_hfp_get_usecase();
2357 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002358 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002359 in_snd_device = hfp_usecase->in_snd_device;
2360 out_snd_device = hfp_usecase->out_snd_device;
2361 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002362 }
2363 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302364 if (usecase->stream.out == NULL) {
2365 ALOGE("%s: stream.out is NULL", __func__);
2366 return -EINVAL;
2367 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002368 usecase->devices = usecase->stream.out->devices;
2369 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002370 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002371 struct stream_out *voip_out = adev->primary_output;
2372 struct stream_in *voip_in = get_voice_communication_input(adev);
Eric Laurentb23d5282013-05-14 15:27:20 -07002373 out_snd_device = platform_get_output_snd_device(adev->platform,
Eric Laurent637e2d42018-11-15 12:24:31 -08002374 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002375 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizdcf967a2018-08-07 17:09:11 +08002376
Eric Laurent637e2d42018-11-15 12:24:31 -08002377 if (voip_usecase)
2378 voip_out = voip_usecase->stream.out;
2379
2380 if (usecase->stream.out == voip_out && voip_in != NULL)
2381 select_devices(adev, voip_in->usecase);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002382 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002383 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302384 if (usecase->stream.in == NULL) {
2385 ALOGE("%s: stream.in is NULL", __func__);
2386 return -EINVAL;
2387 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002388 usecase->devices = usecase->stream.in->device;
2389 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002390 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002391 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Eric Laurent637e2d42018-11-15 12:24:31 -08002392 struct stream_in *voip_in = get_voice_communication_input(adev);
2393
2394 if (voip_in != NULL) {
2395
2396 struct audio_usecase *voip_usecase = get_usecase_from_list(adev,
2397 USECASE_AUDIO_PLAYBACK_VOIP);
2398
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002399 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Eric Laurent637e2d42018-11-15 12:24:31 -08002400 if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2401 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
2402 } else if (voip_usecase) {
2403 out_device = voip_usecase->stream.out->devices;
2404 } else if (adev->primary_output &&
2405 !adev->primary_output->standby) {
2406 out_device = adev->primary_output->devices;
2407 } else {
2408 /* forcing speaker o/p device to get matching i/p pair
2409 in case o/p is not routed from same primary HAL */
2410 out_device = AUDIO_DEVICE_OUT_SPEAKER;
2411 }
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002412 }
Eric Laurent637e2d42018-11-15 12:24:31 -08002413 in_snd_device = platform_get_input_snd_device(adev->platform,
2414 usecase->stream.in,
2415 out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002416 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002417 }
2418 }
2419
2420 if (out_snd_device == usecase->out_snd_device &&
2421 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302422
2423 if (!force_device_switch(usecase))
2424 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002425 }
2426
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302427 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002428 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302429 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2430 return 0;
2431 }
2432
Aalique Grahame22e49102018-12-18 14:23:57 -08002433 if (out_snd_device != SND_DEVICE_NONE &&
2434 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2435 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2436 __func__,
2437 use_case_table[uc_id],
2438 adev->last_logged_snd_device[uc_id][0],
2439 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2440 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2441 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2442 -1,
2443 out_snd_device,
2444 platform_get_snd_device_name(out_snd_device),
2445 platform_get_snd_device_acdb_id(out_snd_device));
2446 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2447 }
2448 if (in_snd_device != SND_DEVICE_NONE &&
2449 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2450 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2451 __func__,
2452 use_case_table[uc_id],
2453 adev->last_logged_snd_device[uc_id][1],
2454 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2455 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2456 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2457 -1,
2458 in_snd_device,
2459 platform_get_snd_device_name(in_snd_device),
2460 platform_get_snd_device_acdb_id(in_snd_device));
2461 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2462 }
2463
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002464
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 /*
2466 * Limitation: While in call, to do a device switch we need to disable
2467 * and enable both RX and TX devices though one of them is same as current
2468 * device.
2469 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002470 if ((usecase->type == VOICE_CALL) &&
2471 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2472 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002473 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002474 }
2475
2476 if (((usecase->type == VOICE_CALL) ||
2477 (usecase->type == VOIP_CALL)) &&
2478 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2479 /* Disable sidetone only if voice/voip call already exists */
2480 if (voice_is_call_state_active(adev) ||
2481 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002482 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002483
2484 /* Disable aanc only if voice call exists */
2485 if (voice_is_call_state_active(adev))
2486 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002487 }
2488
Aalique Grahame22e49102018-12-18 14:23:57 -08002489 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2490 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002491 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302492 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002493 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2494 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2495 else
2496 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302497 }
2498
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002499 /* Disable current sound devices */
2500 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002501 disable_audio_route(adev, usecase);
2502 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002503 }
2504
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002505 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002506 disable_audio_route(adev, usecase);
2507 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002508 }
2509
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002510 /* Applicable only on the targets that has external modem.
2511 * New device information should be sent to modem before enabling
2512 * the devices to reduce in-call device switch time.
2513 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002514 if ((usecase->type == VOICE_CALL) &&
2515 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2516 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002517 status = platform_switch_voice_call_enable_device_config(adev->platform,
2518 out_snd_device,
2519 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002520 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002521
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002522 /* Enable new sound devices */
2523 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002524 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302525 if (platform_check_codec_asrc_support(adev->platform))
2526 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002527 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002528 }
2529
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002530 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302531 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002532 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002533 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002534
Avinash Vaish71a8b972014-07-24 15:36:33 +05302535 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002536 status = platform_switch_voice_call_device_post(adev->platform,
2537 out_snd_device,
2538 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302539 enable_audio_route_for_voice_usecases(adev, usecase);
2540 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002541
sangwoo170731f2013-06-08 15:36:36 +09002542 usecase->in_snd_device = in_snd_device;
2543 usecase->out_snd_device = out_snd_device;
2544
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302545 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2546 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302547 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002548 if ((24 == usecase->stream.out->bit_width) &&
2549 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2550 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2551 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2552 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2553 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2554 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2555 /*
2556 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2557 * configured device sample rate, if not update the COPP rate to be equal to the
2558 * device sample rate, else open COPP at stream sample rate
2559 */
2560 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2561 usecase->stream.out->sample_rate,
2562 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302563 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2564 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002565 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2566 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2567 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2568 }
2569
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002570 /* Notify device change info to effect clients registered */
2571 audio_extn_gef_notify_device_config(
2572 usecase->stream.out->devices,
2573 usecase->stream.out->channel_mask,
2574 usecase->stream.out->app_type_cfg.sample_rate,
2575 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302576 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002577 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002578
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002579 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002580
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002581 /* If input stream is already running then effect needs to be
2582 applied on the new input device that's being enabled here. */
Eric Laurent637e2d42018-11-15 12:24:31 -08002583 if (in_snd_device != SND_DEVICE_NONE)
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002584 check_and_enable_effect(adev);
2585
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002586 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002587 /* Enable aanc only if voice call exists */
2588 if (voice_is_call_state_active(adev))
2589 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2590
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002591 /* Enable sidetone only if other voice/voip call already exists */
2592 if (voice_is_call_state_active(adev) ||
2593 voice_extn_compress_voip_is_started(adev))
2594 voice_set_sidetone(adev, out_snd_device, true);
2595 }
2596
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002597 /* Applicable only on the targets that has external modem.
2598 * Enable device command should be sent to modem only after
2599 * enabling voice call mixer controls
2600 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002601 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002602 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2603 out_snd_device,
2604 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302605
2606 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002607 struct stream_in *in = adev_get_active_input(adev);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302608 if (usecase->type == VOIP_CALL) {
Eric Laurent637e2d42018-11-15 12:24:31 -08002609 if (in != NULL && !in->standby) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302610 if (is_bt_soc_on(adev) == false){
2611 ALOGD("BT SCO MIC disconnected while in connection");
Eric Laurent637e2d42018-11-15 12:24:31 -08002612 if (in->pcm != NULL)
2613 pcm_stop(in->pcm);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302614 }
2615 }
2616 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2617 && usecase->stream.out->started) {
2618 if (is_bt_soc_on(adev) == false) {
2619 ALOGD("BT SCO/A2DP disconnected while in connection");
2620 out_standby_l(&usecase->stream.out->stream.common);
2621 }
2622 }
2623 } else if ((usecase->stream.out != NULL) &&
2624 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302625 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2626 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302627 usecase->stream.out->started) {
2628 if (is_bt_soc_on(adev) == false) {
2629 ALOGD("BT SCO/A2dp disconnected while in connection");
2630 out_standby_l(&usecase->stream.out->stream.common);
2631 }
2632 }
2633 }
2634
Yung Ti Su70cb8242018-06-22 17:38:47 +08002635 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002636 struct stream_out *voip_out = voip_usecase->stream.out;
2637 audio_extn_utils_send_app_type_gain(adev,
2638 voip_out->app_type_cfg.app_type,
2639 &voip_out->app_type_cfg.gain[0]);
2640 }
2641
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302642 ALOGD("%s: done",__func__);
2643
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002644 return status;
2645}
2646
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002647static int stop_input_stream(struct stream_in *in)
2648{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302649 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002650 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302651
2652 if (in == NULL) {
2653 ALOGE("%s: stream_in ptr is NULL", __func__);
2654 return -EINVAL;
2655 }
2656
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 struct audio_device *adev = in->dev;
2658
Eric Laurent994a6932013-07-17 11:51:42 -07002659 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002660 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002661 uc_info = get_usecase_from_list(adev, in->usecase);
2662 if (uc_info == NULL) {
2663 ALOGE("%s: Could not find the usecase (%d) in the list",
2664 __func__, in->usecase);
2665 return -EINVAL;
2666 }
2667
Derek Chenea197282019-01-07 17:35:01 -08002668 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2669 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002670
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002671 /* Close in-call recording streams */
2672 voice_check_and_stop_incall_rec_usecase(adev, in);
2673
Eric Laurent150dbfe2013-02-27 14:31:02 -08002674 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002675 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002676
2677 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002678 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002679
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002680 list_remove(&uc_info->list);
2681 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002682
Vatsal Buchac09ae062018-11-14 13:25:08 +05302683 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002684 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002685 return ret;
2686}
2687
2688int start_input_stream(struct stream_in *in)
2689{
2690 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002691 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002692 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302693
2694 if (in == NULL) {
2695 ALOGE("%s: stream_in ptr is NULL", __func__);
2696 return -EINVAL;
2697 }
2698
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002699 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002700 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002701 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702
Mingming Yin2664a5b2015-09-03 10:53:11 -07002703 if (get_usecase_from_list(adev, usecase) == NULL)
2704 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302705 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2706 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002707
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302708 if (CARD_STATUS_OFFLINE == in->card_status||
2709 CARD_STATUS_OFFLINE == adev->card_status) {
2710 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302711 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302712 goto error_config;
2713 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302714
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302715 if (audio_is_bluetooth_sco_device(in->device)) {
2716 if (!adev->bt_sco_on) {
2717 ALOGE("%s: SCO profile is not ready, return error", __func__);
2718 ret = -EIO;
2719 goto error_config;
2720 }
2721 }
2722
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002723 /* Check if source matches incall recording usecase criteria */
2724 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2725 if (ret)
2726 goto error_config;
2727 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002728 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2729
2730 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2731 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2732 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002733 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002734 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002735
Eric Laurentb23d5282013-05-14 15:27:20 -07002736 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002737 if (in->pcm_device_id < 0) {
2738 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2739 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002740 ret = -EINVAL;
2741 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002742 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002744 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002745
2746 if (!uc_info) {
2747 ret = -ENOMEM;
2748 goto error_config;
2749 }
2750
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002751 uc_info->id = in->usecase;
2752 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002753 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002754 uc_info->devices = in->device;
2755 uc_info->in_snd_device = SND_DEVICE_NONE;
2756 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002757
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002758 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002759 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302760 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2761 adev->perf_lock_opts,
2762 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002763 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002764
Derek Chenea197282019-01-07 17:35:01 -08002765 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2766 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002767
Haynes Mathew George16081042017-05-31 17:16:49 -07002768 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302769 ret = audio_extn_cin_start_input_stream(in);
2770 if (ret)
2771 goto error_open;
2772 else
2773 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002774 }
2775
Haynes Mathew George16081042017-05-31 17:16:49 -07002776 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002777 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002778 ALOGE("%s: pcm stream not ready", __func__);
2779 goto error_open;
2780 }
2781 ret = pcm_start(in->pcm);
2782 if (ret < 0) {
2783 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2784 goto error_open;
2785 }
2786 } else {
2787 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2788 unsigned int pcm_open_retry_count = 0;
2789
2790 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2791 flags |= PCM_MMAP | PCM_NOIRQ;
2792 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2793 } else if (in->realtime) {
2794 flags |= PCM_MMAP | PCM_NOIRQ;
2795 }
2796
Garmond Leunge2433c32017-09-28 21:51:22 -07002797 if (audio_extn_ffv_get_stream() == in) {
2798 ALOGD("%s: ffv stream, update pcm config", __func__);
2799 audio_extn_ffv_update_pcm_config(&config);
2800 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002801 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2802 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2803
2804 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002805 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002806 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002807 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002808 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302809 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302810 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2811 adev->card_status = CARD_STATUS_OFFLINE;
2812 in->card_status = CARD_STATUS_OFFLINE;
2813 ret = -EIO;
2814 goto error_open;
2815 }
2816
Haynes Mathew George16081042017-05-31 17:16:49 -07002817 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2818 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2819 if (in->pcm != NULL) {
2820 pcm_close(in->pcm);
2821 in->pcm = NULL;
2822 }
2823 if (pcm_open_retry_count-- == 0) {
2824 ret = -EIO;
2825 goto error_open;
2826 }
2827 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2828 continue;
2829 }
2830 break;
2831 }
2832
2833 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002834 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002835 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002836 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002837 if (ret < 0) {
2838 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2839 pcm_close(in->pcm);
2840 in->pcm = NULL;
2841 goto error_open;
2842 }
2843 register_in_stream(in);
2844 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002845 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002846 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002847 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002848 if (ret < 0) {
2849 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002850 pcm_close(in->pcm);
2851 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002852 goto error_open;
2853 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002854 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002855 }
2856
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002857 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07002858 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
2859 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002860
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302861done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08002862 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302863 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002864 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302865 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002866 return ret;
2867
2868error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08002869 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302870 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002871 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002872
Eric Laurentc8400632013-02-14 19:04:54 -08002873error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302874 /*
2875 * sleep 50ms to allow sufficient time for kernel
2876 * drivers to recover incases like SSR.
2877 */
2878 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002879 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302880 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002881 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002882}
2883
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002884void lock_input_stream(struct stream_in *in)
2885{
2886 pthread_mutex_lock(&in->pre_lock);
2887 pthread_mutex_lock(&in->lock);
2888 pthread_mutex_unlock(&in->pre_lock);
2889}
2890
2891void lock_output_stream(struct stream_out *out)
2892{
2893 pthread_mutex_lock(&out->pre_lock);
2894 pthread_mutex_lock(&out->lock);
2895 pthread_mutex_unlock(&out->pre_lock);
2896}
2897
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002898/* must be called with out->lock locked */
2899static int send_offload_cmd_l(struct stream_out* out, int command)
2900{
2901 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2902
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002903 if (!cmd) {
2904 ALOGE("failed to allocate mem for command 0x%x", command);
2905 return -ENOMEM;
2906 }
2907
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002908 ALOGVV("%s %d", __func__, command);
2909
2910 cmd->cmd = command;
2911 list_add_tail(&out->offload_cmd_list, &cmd->node);
2912 pthread_cond_signal(&out->offload_cond);
2913 return 0;
2914}
2915
2916/* must be called iwth out->lock locked */
2917static void stop_compressed_output_l(struct stream_out *out)
2918{
2919 out->offload_state = OFFLOAD_STATE_IDLE;
2920 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002921 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002922 if (out->compr != NULL) {
2923 compress_stop(out->compr);
2924 while (out->offload_thread_blocked) {
2925 pthread_cond_wait(&out->cond, &out->lock);
2926 }
2927 }
2928}
2929
Varun Balaraje49253e2017-07-06 19:48:56 +05302930bool is_interactive_usecase(audio_usecase_t uc_id)
2931{
2932 unsigned int i;
2933 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2934 if (uc_id == interactive_usecases[i])
2935 return true;
2936 }
2937 return false;
2938}
2939
2940static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2941{
2942 audio_usecase_t ret_uc = USECASE_INVALID;
2943 unsigned int intract_uc_index;
2944 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2945
2946 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2947 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2948 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2949 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2950 ret_uc = interactive_usecases[intract_uc_index];
2951 break;
2952 }
2953 }
2954
2955 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2956 return ret_uc;
2957}
2958
2959static void free_interactive_usecase(struct audio_device *adev,
2960 audio_usecase_t uc_id)
2961{
2962 unsigned int interact_uc_index;
2963 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2964
2965 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2966 if (interactive_usecases[interact_uc_index] == uc_id) {
2967 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2968 break;
2969 }
2970 }
2971 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2972}
2973
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002974bool is_offload_usecase(audio_usecase_t uc_id)
2975{
2976 unsigned int i;
2977 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2978 if (uc_id == offload_usecases[i])
2979 return true;
2980 }
2981 return false;
2982}
2983
Dhananjay Kumarac341582017-02-23 23:42:25 +05302984static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002985{
vivek mehta446c3962015-09-14 10:57:35 -07002986 audio_usecase_t ret_uc = USECASE_INVALID;
2987 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002988 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002989 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302990 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002991 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2992 else
2993 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002994
vivek mehta446c3962015-09-14 10:57:35 -07002995 pthread_mutex_lock(&adev->lock);
2996 if (get_usecase_from_list(adev, ret_uc) != NULL)
2997 ret_uc = USECASE_INVALID;
2998 pthread_mutex_unlock(&adev->lock);
2999
3000 return ret_uc;
3001 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003002
3003 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07003004 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3005 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
3006 adev->offload_usecases_state |= 0x1 << offload_uc_index;
3007 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003008 break;
3009 }
3010 }
vivek mehta446c3962015-09-14 10:57:35 -07003011
3012 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
3013 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003014}
3015
3016static void free_offload_usecase(struct audio_device *adev,
3017 audio_usecase_t uc_id)
3018{
vivek mehta446c3962015-09-14 10:57:35 -07003019 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08003020 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07003021
3022 if (!adev->multi_offload_enable)
3023 return;
3024
3025 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
3026 if (offload_usecases[offload_uc_index] == uc_id) {
3027 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07003028 break;
3029 }
3030 }
3031 ALOGV("%s: free offload usecase %d", __func__, uc_id);
3032}
3033
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003034static void *offload_thread_loop(void *context)
3035{
3036 struct stream_out *out = (struct stream_out *) context;
3037 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003038 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003039
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003040 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003041 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003042 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3043
3044 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003045 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003046 out->offload_state = OFFLOAD_STATE_IDLE;
3047 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 for (;;) {
3049 struct offload_cmd *cmd = NULL;
3050 stream_callback_event_t event;
3051 bool send_callback = false;
3052
3053 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3054 __func__, list_empty(&out->offload_cmd_list),
3055 out->offload_state);
3056 if (list_empty(&out->offload_cmd_list)) {
3057 ALOGV("%s SLEEPING", __func__);
3058 pthread_cond_wait(&out->offload_cond, &out->lock);
3059 ALOGV("%s RUNNING", __func__);
3060 continue;
3061 }
3062
3063 item = list_head(&out->offload_cmd_list);
3064 cmd = node_to_item(item, struct offload_cmd, node);
3065 list_remove(item);
3066
3067 ALOGVV("%s STATE %d CMD %d out->compr %p",
3068 __func__, out->offload_state, cmd->cmd, out->compr);
3069
3070 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3071 free(cmd);
3072 break;
3073 }
3074
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003075 // allow OFFLOAD_CMD_ERROR reporting during standby
3076 // this is needed to handle failures during compress_open
3077 // Note however that on a pause timeout, the stream is closed
3078 // and no offload usecase will be active. Therefore this
3079 // special case is needed for compress_open failures alone
3080 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3081 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003082 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003083 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003084 pthread_cond_signal(&out->cond);
3085 continue;
3086 }
3087 out->offload_thread_blocked = true;
3088 pthread_mutex_unlock(&out->lock);
3089 send_callback = false;
3090 switch(cmd->cmd) {
3091 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003092 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003093 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003094 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003095 send_callback = true;
3096 event = STREAM_CBK_EVENT_WRITE_READY;
3097 break;
3098 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003099 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303100 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003101 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303102 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003103 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303104 if (ret < 0)
3105 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303106 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303107 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003108 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003109 else
3110 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003111 if (-ENETRESET != ret && !(-EINTR == ret &&
3112 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303113 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303114 pthread_mutex_lock(&out->lock);
3115 out->send_new_metadata = 1;
3116 out->send_next_track_params = true;
3117 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303118 event = STREAM_CBK_EVENT_DRAIN_READY;
3119 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3120 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303121 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003122 break;
3123 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003124 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003125 ret = compress_drain(out->compr);
3126 ALOGD("copl(%p):out of compress_drain", out);
3127 // EINTR check avoids drain interruption due to SSR
3128 if (-ENETRESET != ret && !(-EINTR == ret &&
3129 CARD_STATUS_OFFLINE == out->card_status)) {
3130 send_callback = true;
3131 event = STREAM_CBK_EVENT_DRAIN_READY;
3132 } else
3133 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003134 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303135 case OFFLOAD_CMD_ERROR:
3136 ALOGD("copl(%p): sending error callback to AF", out);
3137 send_callback = true;
3138 event = STREAM_CBK_EVENT_ERROR;
3139 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003140 default:
3141 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3142 break;
3143 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003144 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003145 out->offload_thread_blocked = false;
3146 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003147 if (send_callback && out->client_callback) {
3148 ALOGVV("%s: sending client_callback event %d", __func__, event);
3149 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003150 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003151 free(cmd);
3152 }
3153
3154 pthread_cond_signal(&out->cond);
3155 while (!list_empty(&out->offload_cmd_list)) {
3156 item = list_head(&out->offload_cmd_list);
3157 list_remove(item);
3158 free(node_to_item(item, struct offload_cmd, node));
3159 }
3160 pthread_mutex_unlock(&out->lock);
3161
3162 return NULL;
3163}
3164
3165static int create_offload_callback_thread(struct stream_out *out)
3166{
3167 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3168 list_init(&out->offload_cmd_list);
3169 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3170 offload_thread_loop, out);
3171 return 0;
3172}
3173
3174static int destroy_offload_callback_thread(struct stream_out *out)
3175{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003176 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003177 stop_compressed_output_l(out);
3178 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3179
3180 pthread_mutex_unlock(&out->lock);
3181 pthread_join(out->offload_thread, (void **) NULL);
3182 pthread_cond_destroy(&out->offload_cond);
3183
3184 return 0;
3185}
3186
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003187static int stop_output_stream(struct stream_out *out)
3188{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303189 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003190 struct audio_usecase *uc_info;
3191 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003192 bool has_voip_usecase =
3193 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003194
Eric Laurent994a6932013-07-17 11:51:42 -07003195 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003196 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003197 uc_info = get_usecase_from_list(adev, out->usecase);
3198 if (uc_info == NULL) {
3199 ALOGE("%s: Could not find the usecase (%d) in the list",
3200 __func__, out->usecase);
3201 return -EINVAL;
3202 }
3203
Derek Chenea197282019-01-07 17:35:01 -08003204 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3205 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003206
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003207 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303208 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003209 if (adev->visualizer_stop_output != NULL)
3210 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003211
3212 audio_extn_dts_remove_state_notifier_node(out->usecase);
3213
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003214 if (adev->offload_effects_stop_output != NULL)
3215 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003216 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3217 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3218 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003219 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003220
Arun Mirpurief53ce52018-09-11 18:00:09 -07003221 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3222 voice_set_device_mute_flag(adev, false);
3223
Eric Laurent150dbfe2013-02-27 14:31:02 -08003224 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003225 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003226
3227 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003228 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003229
Aalique Grahame22e49102018-12-18 14:23:57 -08003230 audio_extn_extspk_update(adev->extspk);
3231
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003232 if (is_offload_usecase(out->usecase)) {
3233 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3234 adev->dsp_bit_width_enforce_mode,
3235 false);
3236 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003237 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3238 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3239 false);
3240
3241 if (ret != 0)
3242 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3243 /* default service interval was successfully updated,
3244 reopen USB backend with new service interval */
3245 ret = 0;
3246 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003247
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003248 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303249 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003250 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303251 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003252 ALOGV("Disable passthrough , reset mixer to pcm");
3253 /* NO_PASSTHROUGH */
3254 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003255 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003256 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3257 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003258
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303259 /* Must be called after removing the usecase from list */
3260 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303261 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303262
Manish Dewangan21a850a2017-08-14 12:03:55 +05303263 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003264 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3265 if (ret < 0)
3266 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3267 }
3268
juyuchen2d415992018-11-16 14:15:16 +08003269 /* 1) media + voip output routing to handset must route media back to
3270 speaker when voip stops.
3271 2) trigger voip input to reroute when voip output changes to
3272 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003273 if (has_voip_usecase ||
3274 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3275 struct listnode *node;
3276 struct audio_usecase *usecase;
3277 list_for_each(node, &adev->usecase_list) {
3278 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003279 if ((usecase->type == PCM_CAPTURE &&
3280 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3281 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003282 continue;
3283
3284 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3285 __func__, usecase->id, use_case_table[usecase->id],
3286 out->usecase, use_case_table[out->usecase]);
3287 select_devices(adev, usecase->id);
3288 }
3289 }
3290
Garmond Leung5fd0b552018-04-17 11:56:12 -07003291 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003292 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293 return ret;
3294}
3295
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003296struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3297 unsigned int flags, unsigned int pcm_open_retry_count,
3298 struct pcm_config *config)
3299{
3300 struct pcm* pcm = NULL;
3301
3302 while (1) {
3303 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3304 if (pcm == NULL || !pcm_is_ready(pcm)) {
3305 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3306 if (pcm != NULL) {
3307 pcm_close(pcm);
3308 pcm = NULL;
3309 }
3310 if (pcm_open_retry_count-- == 0)
3311 return NULL;
3312
3313 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3314 continue;
3315 }
3316 break;
3317 }
3318
3319 if (pcm_is_ready(pcm)) {
3320 int ret = pcm_prepare(pcm);
3321 if (ret < 0) {
3322 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3323 pcm_close(pcm);
3324 pcm = NULL;
3325 }
3326 }
3327
3328 return pcm;
3329}
3330
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003331int start_output_stream(struct stream_out *out)
3332{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003333 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003334 struct audio_usecase *uc_info;
3335 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003336 char mixer_ctl_name[128];
3337 struct mixer_ctl *ctl = NULL;
3338 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303339 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003340 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003341
Haynes Mathew George380745d2017-10-04 15:27:45 -07003342 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003343 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3344 ret = -EINVAL;
3345 goto error_config;
3346 }
3347
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003348 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303349 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003350 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303351
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303352 if (CARD_STATUS_OFFLINE == out->card_status ||
3353 CARD_STATUS_OFFLINE == adev->card_status) {
3354 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303355 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303356 goto error_config;
3357 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303358
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303359 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003360 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003361 if (out->devices &
3362 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303363 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303364 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303365 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3366 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3367 ret = -EAGAIN;
3368 goto error_config;
3369 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303370 }
3371 }
3372 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303373 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3374 if (!adev->bt_sco_on) {
3375 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3376 //combo usecase just by pass a2dp
3377 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3378 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3379 } else {
3380 ALOGE("%s: SCO profile is not ready, return error", __func__);
3381 ret = -EAGAIN;
3382 goto error_config;
3383 }
3384 }
3385 }
3386
Eric Laurentb23d5282013-05-14 15:27:20 -07003387 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003388 if (out->pcm_device_id < 0) {
3389 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3390 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003391 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003392 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003393 }
3394
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003395 if (is_haptic_usecase) {
3396 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3397 if (adev->haptic_pcm_device_id < 0) {
3398 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3399 __func__, adev->haptic_pcm_device_id, out->usecase);
3400 ret = -EINVAL;
3401 goto error_config;
3402 }
3403 }
3404
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003405 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003406
3407 if (!uc_info) {
3408 ret = -ENOMEM;
3409 goto error_config;
3410 }
3411
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003412 uc_info->id = out->usecase;
3413 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003414 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003415 uc_info->devices = out->devices;
3416 uc_info->in_snd_device = SND_DEVICE_NONE;
3417 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003418
3419 /* This must be called before adding this usecase to the list */
3420 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3421 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3422 /* USB backend is not reopened immediately.
3423 This is eventually done as part of select_devices */
3424 }
3425
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003426 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003427
Wei Wangf7ca6c92017-11-21 14:51:20 -08003428 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303429 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3430 adev->perf_lock_opts,
3431 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303432
3433 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303434 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303435 if (audio_extn_passthru_is_enabled() &&
3436 audio_extn_passthru_is_passthrough_stream(out)) {
3437 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303438 }
3439 }
3440
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303441 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003442 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303443 if (!a2dp_combo) {
3444 check_a2dp_restore_l(adev, out, false);
3445 } else {
3446 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003447 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3448 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3449 else
3450 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303451 select_devices(adev, out->usecase);
3452 out->devices = dev;
3453 }
3454 } else {
3455 select_devices(adev, out->usecase);
3456 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003457
Arun Mirpurief53ce52018-09-11 18:00:09 -07003458 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3459 voice_set_device_mute_flag(adev, true);
3460
Derek Chenea197282019-01-07 17:35:01 -08003461 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3462 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003463
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003464 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3465 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003466
3467 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003468 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003469 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3470 ALOGE("%s: pcm stream not ready", __func__);
3471 goto error_open;
3472 }
3473 ret = pcm_start(out->pcm);
3474 if (ret < 0) {
3475 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3476 goto error_open;
3477 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003478 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003479 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003480 unsigned int flags = PCM_OUT;
3481 unsigned int pcm_open_retry_count = 0;
3482 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3483 flags |= PCM_MMAP | PCM_NOIRQ;
3484 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003485 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003486 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003487 } else
3488 flags |= PCM_MONOTONIC;
3489
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003490 if ((adev->vr_audio_mode_enabled) &&
3491 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3492 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3493 "PCM_Dev %d Topology", out->pcm_device_id);
3494 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3495 if (!ctl) {
3496 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3497 __func__, mixer_ctl_name);
3498 } else {
3499 //if success use ULLPP
3500 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3501 __func__, mixer_ctl_name, out->pcm_device_id);
3502 //There is a still a possibility that some sessions
3503 // that request for FAST|RAW when 3D audio is active
3504 //can go through ULLPP. Ideally we expects apps to
3505 //listen to audio focus and stop concurrent playback
3506 //Also, we will look for mode flag (voice_in_communication)
3507 //before enabling the realtime flag.
3508 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3509 }
3510 }
3511
Surendar Karka91fa3682018-07-02 18:12:12 +05303512 if (out->realtime)
3513 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3514 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3515
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003516 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3517 flags, pcm_open_retry_count,
3518 &(out->config));
3519 if (out->pcm == NULL) {
3520 ret = -EIO;
3521 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003522 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003523
3524 if (is_haptic_usecase) {
3525 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3526 adev->haptic_pcm_device_id,
3527 flags, pcm_open_retry_count,
3528 &(adev->haptics_config));
3529 // failure to open haptics pcm shouldnt stop audio,
3530 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003531
3532 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3533 ALOGD("%s: enable haptic audio synchronization", __func__);
3534 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3535 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003536 }
3537
Surendar Karka91fa3682018-07-02 18:12:12 +05303538 if (!out->realtime)
3539 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303540 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003541
Zhou Song2b8f28f2017-09-11 10:51:38 +08003542 // apply volume for voip playback after path is set up
3543 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3544 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303545 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3546 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303547 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3548 out->apply_volume = false;
3549 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003550 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003551 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303552 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003553 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3554 adev->dsp_bit_width_enforce_mode,
3555 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003557 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003558 out->compr = compress_open(adev->snd_card,
3559 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003560 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003561 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303562 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303563 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3564 adev->card_status = CARD_STATUS_OFFLINE;
3565 out->card_status = CARD_STATUS_OFFLINE;
3566 ret = -EIO;
3567 goto error_open;
3568 }
3569
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003570 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003571 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003572 compress_close(out->compr);
3573 out->compr = NULL;
3574 ret = -EIO;
3575 goto error_open;
3576 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303577 /* compress_open sends params of the track, so reset the flag here */
3578 out->is_compr_metadata_avail = false;
3579
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003580 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003581 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003582
Fred Oh3f43e742015-03-04 18:42:34 -08003583 /* Since small bufs uses blocking writes, a write will be blocked
3584 for the default max poll time (20s) in the event of an SSR.
3585 Reduce the poll time to observe and deal with SSR faster.
3586 */
Ashish Jain5106d362016-05-11 19:23:33 +05303587 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003588 compress_set_max_poll_wait(out->compr, 1000);
3589 }
3590
Manish Dewangan69426c82017-01-30 17:35:36 +05303591 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303592 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303593
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003594 audio_extn_dts_create_state_notifier_node(out->usecase);
3595 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3596 popcount(out->channel_mask),
3597 out->playback_started);
3598
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003599#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303600 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003601 audio_extn_dolby_send_ddp_endp_params(adev);
3602#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303603 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3604 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003605 if (adev->visualizer_start_output != NULL)
3606 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3607 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303608 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003609 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003610 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003611 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003612
3613 if (ret == 0) {
3614 register_out_stream(out);
3615 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003616 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3617 ALOGE("%s: pcm stream not ready", __func__);
3618 goto error_open;
3619 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003620 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003621 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003622 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003623 if (ret < 0)
3624 goto error_open;
3625 }
3626 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003627 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303628 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003629 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003630
vivek mehtad15d2bf2019-05-17 13:35:10 -07003631 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3632 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3633 audio_low_latency_hint_start();
3634 }
3635
Manish Dewangan21a850a2017-08-14 12:03:55 +05303636 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003637 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003638 if (ret < 0)
3639 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3640 }
3641
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003642 // consider a scenario where on pause lower layers are tear down.
3643 // so on resume, swap mixer control need to be sent only when
3644 // backend is active, hence rather than sending from enable device
3645 // sending it from start of streamtream
3646
3647 platform_set_swap_channels(adev, true);
3648
Haynes Mathew George380745d2017-10-04 15:27:45 -07003649 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303650 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003651 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003652error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003653 if (adev->haptic_pcm) {
3654 pcm_close(adev->haptic_pcm);
3655 adev->haptic_pcm = NULL;
3656 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003657 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303658 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003659 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003660error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303661 /*
3662 * sleep 50ms to allow sufficient time for kernel
3663 * drivers to recover incases like SSR.
3664 */
3665 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003666 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303667 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003668 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003669}
3670
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003671static int check_input_parameters(uint32_t sample_rate,
3672 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003673 int channel_count,
3674 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003675{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003676 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003677
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303678 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3679 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3680 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003681 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003682 !audio_extn_compr_cap_format_supported(format) &&
3683 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003684 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003685
Aalique Grahame22e49102018-12-18 14:23:57 -08003686 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3687 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3688 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3689 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3690 return -EINVAL;
3691 }
3692
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003693 switch (channel_count) {
3694 case 1:
3695 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303696 case 3:
3697 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003698 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003699 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003700 break;
3701 default:
3702 ret = -EINVAL;
3703 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003704
3705 switch (sample_rate) {
3706 case 8000:
3707 case 11025:
3708 case 12000:
3709 case 16000:
3710 case 22050:
3711 case 24000:
3712 case 32000:
3713 case 44100:
3714 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003715 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303716 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003717 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303718 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719 break;
3720 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003721 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003722 }
3723
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003724 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003725}
3726
Naresh Tanniru04f71882018-06-26 17:46:22 +05303727
3728/** Add a value in a list if not already present.
3729 * @return true if value was successfully inserted or already present,
3730 * false if the list is full and does not contain the value.
3731 */
3732static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3733 for (size_t i = 0; i < list_length; i++) {
3734 if (list[i] == value) return true; // value is already present
3735 if (list[i] == 0) { // no values in this slot
3736 list[i] = value;
3737 return true; // value inserted
3738 }
3739 }
3740 return false; // could not insert value
3741}
3742
3743/** Add channel_mask in supported_channel_masks if not already present.
3744 * @return true if channel_mask was successfully inserted or already present,
3745 * false if supported_channel_masks is full and does not contain channel_mask.
3746 */
3747static void register_channel_mask(audio_channel_mask_t channel_mask,
3748 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3749 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3750 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3751}
3752
3753/** Add format in supported_formats if not already present.
3754 * @return true if format was successfully inserted or already present,
3755 * false if supported_formats is full and does not contain format.
3756 */
3757static void register_format(audio_format_t format,
3758 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3759 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3760 "%s: stream can not declare supporting its format %x", __func__, format);
3761}
3762/** Add sample_rate in supported_sample_rates if not already present.
3763 * @return true if sample_rate was successfully inserted or already present,
3764 * false if supported_sample_rates is full and does not contain sample_rate.
3765 */
3766static void register_sample_rate(uint32_t sample_rate,
3767 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3768 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3769 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3770}
3771
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003772static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3773{
3774 uint32_t high = num1, low = num2, temp = 0;
3775
3776 if (!num1 || !num2)
3777 return 0;
3778
3779 if (num1 < num2) {
3780 high = num2;
3781 low = num1;
3782 }
3783
3784 while (low != 0) {
3785 temp = low;
3786 low = high % low;
3787 high = temp;
3788 }
3789 return (num1 * num2)/high;
3790}
3791
3792static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3793{
3794 uint32_t remainder = 0;
3795
3796 if (!multiplier)
3797 return num;
3798
3799 remainder = num % multiplier;
3800 if (remainder)
3801 num += (multiplier - remainder);
3802
3803 return num;
3804}
3805
Aalique Grahame22e49102018-12-18 14:23:57 -08003806static size_t get_stream_buffer_size(size_t duration_ms,
3807 uint32_t sample_rate,
3808 audio_format_t format,
3809 int channel_count,
3810 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003811{
3812 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003813 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814
Aalique Grahame22e49102018-12-18 14:23:57 -08003815 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003816 if (is_low_latency)
3817 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303818
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003819 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003820 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003821
Ralf Herzbd08d632018-09-28 15:50:49 +02003822 /* make sure the size is multiple of 32 bytes and additionally multiple of
3823 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003824 * At 48 kHz mono 16-bit PCM:
3825 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3826 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003827 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003828 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003829 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003830
3831 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003832}
3833
Aalique Grahame22e49102018-12-18 14:23:57 -08003834static size_t get_input_buffer_size(uint32_t sample_rate,
3835 audio_format_t format,
3836 int channel_count,
3837 bool is_low_latency)
3838{
3839 /* Don't know if USB HIFI in this context so use true to be conservative */
3840 if (check_input_parameters(sample_rate, format, channel_count,
3841 true /*is_usb_hifi */) != 0)
3842 return 0;
3843
3844 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3845 sample_rate,
3846 format,
3847 channel_count,
3848 is_low_latency);
3849}
3850
Ashish Jain058165c2016-09-28 23:18:48 +05303851static size_t get_output_period_size(uint32_t sample_rate,
3852 audio_format_t format,
3853 int channel_count,
3854 int duration /*in millisecs*/)
3855{
3856 size_t size = 0;
3857 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3858
3859 if ((duration == 0) || (sample_rate == 0) ||
3860 (bytes_per_sample == 0) || (channel_count == 0)) {
3861 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3862 bytes_per_sample, channel_count);
3863 return -EINVAL;
3864 }
3865
3866 size = (sample_rate *
3867 duration *
3868 bytes_per_sample *
3869 channel_count) / 1000;
3870 /*
3871 * To have same PCM samples for all channels, the buffer size requires to
3872 * be multiple of (number of channels * bytes per sample)
3873 * For writes to succeed, the buffer must be written at address which is multiple of 32
3874 */
3875 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3876
3877 return (size/(channel_count * bytes_per_sample));
3878}
3879
Zhou Song48453a02018-01-10 17:50:59 +08003880static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303881{
3882 uint64_t actual_frames_rendered = 0;
3883 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3884
3885 /* This adjustment accounts for buffering after app processor.
3886 * It is based on estimated DSP latency per use case, rather than exact.
3887 */
3888 int64_t platform_latency = platform_render_latency(out->usecase) *
3889 out->sample_rate / 1000000LL;
3890
Zhou Song48453a02018-01-10 17:50:59 +08003891 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303892 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3893 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3894 * hence only estimate.
3895 */
3896 int64_t signed_frames = out->written - kernel_buffer_size;
3897
3898 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3899
Zhou Song48453a02018-01-10 17:50:59 +08003900 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303901 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003902 if (timestamp != NULL )
3903 *timestamp = out->writeAt;
3904 } else if (timestamp != NULL) {
3905 clock_gettime(CLOCK_MONOTONIC, timestamp);
3906 }
3907 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303908
3909 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3910 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3911 (long long int)out->written, (int)kernel_buffer_size,
3912 audio_bytes_per_sample(out->compr_config.codec->format),
3913 popcount(out->channel_mask));
3914
3915 return actual_frames_rendered;
3916}
3917
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003918static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3919{
3920 struct stream_out *out = (struct stream_out *)stream;
3921
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003922 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003923}
3924
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003925static int out_set_sample_rate(struct audio_stream *stream __unused,
3926 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003927{
3928 return -ENOSYS;
3929}
3930
3931static size_t out_get_buffer_size(const struct audio_stream *stream)
3932{
3933 struct stream_out *out = (struct stream_out *)stream;
3934
Varun Balaraje49253e2017-07-06 19:48:56 +05303935 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303936 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303937 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303938 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3939 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3940 else
3941 return out->compr_config.fragment_size;
3942 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003943 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003944 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3945 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 +05303946 else if (is_offload_usecase(out->usecase) &&
3947 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303948 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003949
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003950 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003951 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003952}
3953
3954static uint32_t out_get_channels(const struct audio_stream *stream)
3955{
3956 struct stream_out *out = (struct stream_out *)stream;
3957
3958 return out->channel_mask;
3959}
3960
3961static audio_format_t out_get_format(const struct audio_stream *stream)
3962{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003963 struct stream_out *out = (struct stream_out *)stream;
3964
3965 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003966}
3967
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003968static int out_set_format(struct audio_stream *stream __unused,
3969 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003970{
3971 return -ENOSYS;
3972}
3973
3974static int out_standby(struct audio_stream *stream)
3975{
3976 struct stream_out *out = (struct stream_out *)stream;
3977 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003978 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003979
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303980 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3981 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003982
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003983 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003984 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003985 if (adev->adm_deregister_stream)
3986 adev->adm_deregister_stream(adev->adm_data, out->handle);
3987
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003988 if (is_offload_usecase(out->usecase))
3989 stop_compressed_output_l(out);
3990
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003991 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003992 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003993 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3994 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303995 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003996 pthread_mutex_unlock(&adev->lock);
3997 pthread_mutex_unlock(&out->lock);
3998 ALOGD("VOIP output entered standby");
3999 return 0;
4000 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004001 if (out->pcm) {
4002 pcm_close(out->pcm);
4003 out->pcm = NULL;
4004 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004005 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4006 do_stop = out->playback_started;
4007 out->playback_started = false;
4008 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004009 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07004010 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05304011 out->send_next_track_params = false;
4012 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004013 out->gapless_mdata.encoder_delay = 0;
4014 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004015 if (out->compr != NULL) {
4016 compress_close(out->compr);
4017 out->compr = NULL;
4018 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004019 }
Haynes Mathew George16081042017-05-31 17:16:49 -07004020 if (do_stop) {
4021 stop_output_stream(out);
4022 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08004023 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004024 }
4025 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05304026 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004027 return 0;
4028}
4029
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304030static int out_on_error(struct audio_stream *stream)
4031{
4032 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004033 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304034
4035 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004036 // always send CMD_ERROR for offload streams, this
4037 // is needed e.g. when SSR happens within compress_open
4038 // since the stream is active, offload_callback_thread is also active.
4039 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4040 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004041 }
4042 pthread_mutex_unlock(&out->lock);
4043
4044 status = out_standby(&out->stream.common);
4045
4046 lock_output_stream(out);
4047 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004048 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304049 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304050
4051 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4052 ALOGD("Setting previous card status if offline");
4053 out->prev_card_status_offline = true;
4054 }
4055
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304056 pthread_mutex_unlock(&out->lock);
4057
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004058 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304059}
4060
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304061/*
4062 *standby implementation without locks, assumes that the callee already
4063 *has taken adev and out lock.
4064 */
4065int out_standby_l(struct audio_stream *stream)
4066{
4067 struct stream_out *out = (struct stream_out *)stream;
4068 struct audio_device *adev = out->dev;
4069
4070 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4071 stream, out->usecase, use_case_table[out->usecase]);
4072
4073 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004074 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304075 if (adev->adm_deregister_stream)
4076 adev->adm_deregister_stream(adev->adm_data, out->handle);
4077
4078 if (is_offload_usecase(out->usecase))
4079 stop_compressed_output_l(out);
4080
4081 out->standby = true;
4082 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4083 voice_extn_compress_voip_close_output_stream(stream);
4084 out->started = 0;
4085 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004086 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304087 return 0;
4088 } else if (!is_offload_usecase(out->usecase)) {
4089 if (out->pcm) {
4090 pcm_close(out->pcm);
4091 out->pcm = NULL;
4092 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004093 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4094 if (adev->haptic_pcm) {
4095 pcm_close(adev->haptic_pcm);
4096 adev->haptic_pcm = NULL;
4097 }
4098
4099 if (adev->haptic_buffer != NULL) {
4100 free(adev->haptic_buffer);
4101 adev->haptic_buffer = NULL;
4102 adev->haptic_buffer_size = 0;
4103 }
4104 adev->haptic_pcm_device_id = 0;
4105 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304106 } else {
4107 ALOGD("copl(%p):standby", out);
4108 out->send_next_track_params = false;
4109 out->is_compr_metadata_avail = false;
4110 out->gapless_mdata.encoder_delay = 0;
4111 out->gapless_mdata.encoder_padding = 0;
4112 if (out->compr != NULL) {
4113 compress_close(out->compr);
4114 out->compr = NULL;
4115 }
4116 }
4117 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004118 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304119 }
4120 ALOGD("%s: exit", __func__);
4121 return 0;
4122}
4123
Aalique Grahame22e49102018-12-18 14:23:57 -08004124static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004125{
Aalique Grahame22e49102018-12-18 14:23:57 -08004126 struct stream_out *out = (struct stream_out *)stream;
4127
4128 // We try to get the lock for consistency,
4129 // but it isn't necessary for these variables.
4130 // If we're not in standby, we may be blocked on a write.
4131 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4132 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4133 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4134
4135 if (locked) {
4136 pthread_mutex_unlock(&out->lock);
4137 }
4138
4139 // dump error info
4140 (void)error_log_dump(
4141 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4142
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004143 return 0;
4144}
4145
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004146static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4147{
4148 int ret = 0;
4149 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004150
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004151 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004152 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004153 return -EINVAL;
4154 }
4155
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304156 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004157
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004158 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4159 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304160 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004161 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004162 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4163 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304164 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004165 }
4166
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004167 ALOGV("%s new encoder delay %u and padding %u", __func__,
4168 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4169
4170 return 0;
4171}
4172
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004173static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4174{
4175 return out == adev->primary_output || out == adev->voice_tx_output;
4176}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004177
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304178// note: this call is safe only if the stream_cb is
4179// removed first in close_output_stream (as is done now).
4180static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4181{
4182 if (!stream || !parms)
4183 return;
4184
4185 struct stream_out *out = (struct stream_out *)stream;
4186 struct audio_device *adev = out->dev;
4187
4188 card_status_t status;
4189 int card;
4190 if (parse_snd_card_status(parms, &card, &status) < 0)
4191 return;
4192
4193 pthread_mutex_lock(&adev->lock);
4194 bool valid_cb = (card == adev->snd_card);
4195 pthread_mutex_unlock(&adev->lock);
4196
4197 if (!valid_cb)
4198 return;
4199
4200 lock_output_stream(out);
4201 if (out->card_status != status)
4202 out->card_status = status;
4203 pthread_mutex_unlock(&out->lock);
4204
4205 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4206 use_case_table[out->usecase],
4207 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4208
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304209 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304210 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304211 if (voice_is_call_state_active(adev) &&
4212 out == adev->primary_output) {
4213 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4214 pthread_mutex_lock(&adev->lock);
4215 voice_stop_call(adev);
4216 adev->mode = AUDIO_MODE_NORMAL;
4217 pthread_mutex_unlock(&adev->lock);
4218 }
4219 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304220 return;
4221}
4222
Kevin Rocardfce19002017-08-07 19:21:36 -07004223static int get_alive_usb_card(struct str_parms* parms) {
4224 int card;
4225 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4226 !audio_extn_usb_alive(card)) {
4227 return card;
4228 }
4229 return -ENODEV;
4230}
4231
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004232static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4233{
4234 struct stream_out *out = (struct stream_out *)stream;
4235 struct audio_device *adev = out->dev;
4236 struct str_parms *parms;
4237 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004238 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304239 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004240 bool reconfig = false;
4241 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004242
sangwoobc677242013-08-08 16:53:43 +09004243 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004244 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004245 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304246 if (!parms)
4247 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004248 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4249 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004250 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004251 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004252 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004253
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004254 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004255 * When HDMI cable is unplugged the music playback is paused and
4256 * the policy manager sends routing=0. But the audioflinger continues
4257 * to write data until standby time (3sec). As the HDMI core is
4258 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004259 * Avoid this by routing audio to speaker until standby.
4260 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004261 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4262 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304263 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004264 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4265 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004266 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304267 /*
4268 * When A2DP is disconnected the
4269 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004270 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304271 * (3sec). As BT is turned off, the write gets blocked.
4272 * Avoid this by routing audio to speaker until standby.
4273 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004274 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004275 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004276 !audio_extn_a2dp_source_is_ready() &&
4277 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304278 val = AUDIO_DEVICE_OUT_SPEAKER;
4279 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304280 /*
4281 * When USB headset is disconnected the music platback paused
4282 * and the policy manager send routing=0. But if the USB is connected
4283 * back before the standby time, AFE is not closed and opened
4284 * when USB is connected back. So routing to speker will guarantee
4285 * AFE reconfiguration and AFE will be opend once USB is connected again
4286 */
4287 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4288 (val == AUDIO_DEVICE_NONE) &&
4289 !audio_extn_usb_connected(parms)) {
4290 val = AUDIO_DEVICE_OUT_SPEAKER;
4291 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304292 /* To avoid a2dp to sco overlapping / BT device improper state
4293 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304294 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304295 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004296 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004297 if (val &
4298 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304299 //combo usecase just by pass a2dp
4300 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304301 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304302 } else {
4303 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4304 /* update device to a2dp and don't route as BT returned error
4305 * However it is still possible a2dp routing called because
4306 * of current active device disconnection (like wired headset)
4307 */
4308 out->devices = val;
4309 pthread_mutex_unlock(&out->lock);
4310 pthread_mutex_unlock(&adev->lock);
4311 goto error;
4312 }
4313 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304314 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004315
4316 audio_devices_t new_dev = val;
4317
4318 // Workaround: If routing to an non existing usb device, fail gracefully
4319 // The routing request will otherwise block during 10 second
4320 int card;
4321 if (audio_is_usb_out_device(new_dev) &&
4322 (card = get_alive_usb_card(parms)) >= 0) {
4323
4324 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4325 pthread_mutex_unlock(&adev->lock);
4326 pthread_mutex_unlock(&out->lock);
4327 ret = -ENOSYS;
4328 goto routing_fail;
4329 }
4330
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004331 /*
4332 * select_devices() call below switches all the usecases on the same
4333 * backend to the new device. Refer to check_usecases_codec_backend() in
4334 * the select_devices(). But how do we undo this?
4335 *
4336 * For example, music playback is active on headset (deep-buffer usecase)
4337 * and if we go to ringtones and select a ringtone, low-latency usecase
4338 * will be started on headset+speaker. As we can't enable headset+speaker
4339 * and headset devices at the same time, select_devices() switches the music
4340 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4341 * So when the ringtone playback is completed, how do we undo the same?
4342 *
4343 * We are relying on the out_set_parameters() call on deep-buffer output,
4344 * once the ringtone playback is ended.
4345 * NOTE: We should not check if the current devices are same as new devices.
4346 * Because select_devices() must be called to switch back the music
4347 * playback to headset.
4348 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004349 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004350 audio_devices_t new_dev = val;
4351 bool same_dev = out->devices == new_dev;
4352 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004353
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004354 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004355 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004356 if (adev->mode == AUDIO_MODE_IN_CALL) {
4357 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004358 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4359 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4360 audio_extn_usb_set_service_interval(true /*playback*/,
4361 service_interval,
4362 &reconfig);
4363 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4364 }
4365 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004366 }
4367 } else {
4368 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004369 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004370 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004371 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004372
4373 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004374 if (!same_dev) {
4375 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304376 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4377 adev->perf_lock_opts,
4378 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004379 if (adev->adm_on_routing_change)
4380 adev->adm_on_routing_change(adev->adm_data,
4381 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004382 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304383 if (!bypass_a2dp) {
4384 select_devices(adev, out->usecase);
4385 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004386 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4387 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4388 else
4389 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304390 select_devices(adev, out->usecase);
4391 out->devices = new_dev;
4392 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004393
4394 if (!same_dev) {
4395 // on device switch force swap, lower functions will make sure
4396 // to check if swap is allowed or not.
4397 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304398 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004399 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304400 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4401 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004402 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304403 pthread_mutex_lock(&out->compr_mute_lock);
4404 out->a2dp_compress_mute = false;
4405 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4406 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004407 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4408 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304409 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004410 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004411 }
4412
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004413 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004414 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004415
4416 /*handles device and call state changes*/
4417 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004418 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004419 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004420
4421 if (out == adev->primary_output) {
4422 pthread_mutex_lock(&adev->lock);
4423 audio_extn_set_parameters(adev, parms);
4424 pthread_mutex_unlock(&adev->lock);
4425 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004426 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004427 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004428 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004429
4430 audio_extn_dts_create_state_notifier_node(out->usecase);
4431 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4432 popcount(out->channel_mask),
4433 out->playback_started);
4434
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004435 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004436 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004437
Surendar Karkaf51b5842018-04-26 11:28:38 +05304438 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4439 sizeof(value));
4440 if (err >= 0) {
4441 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4442 audio_extn_send_dual_mono_mixing_coefficients(out);
4443 }
4444
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304445 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4446 if (err >= 0) {
4447 strlcpy(out->profile, value, sizeof(out->profile));
4448 ALOGV("updating stream profile with value '%s'", out->profile);
4449 lock_output_stream(out);
4450 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4451 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004452 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304453 out->sample_rate, out->bit_width,
4454 out->channel_mask, out->profile,
4455 &out->app_type_cfg);
4456 pthread_mutex_unlock(&out->lock);
4457 }
4458
Alexy Joseph98988832017-01-13 14:56:59 -08004459 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004460 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4461 // and vendor.audio.hal.output.suspend.supported is set to true
4462 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004463 //check suspend parameter only for low latency and if the property
4464 //is enabled
4465 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4466 ALOGI("%s: got suspend_playback %s", __func__, value);
4467 lock_output_stream(out);
4468 if (!strncmp(value, "false", 5)) {
4469 //suspend_playback=false is supposed to set QOS value back to 75%
4470 //the mixer control sent with value Enable will achieve that
4471 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4472 } else if (!strncmp (value, "true", 4)) {
4473 //suspend_playback=true is supposed to remove QOS value
4474 //resetting the mixer control will set the default value
4475 //for the mixer control which is Disable and this removes the QOS vote
4476 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4477 } else {
4478 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4479 " got %s", __func__, value);
4480 ret = -1;
4481 }
4482
4483 if (ret != 0) {
4484 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4485 __func__, out->pm_qos_mixer_path, ret);
4486 }
4487
4488 pthread_mutex_unlock(&out->lock);
4489 }
4490 }
4491 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004492 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304493error:
Eric Laurent994a6932013-07-17 11:51:42 -07004494 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004495 return ret;
4496}
4497
Paul McLeana50b7332018-12-17 08:24:21 -07004498static int in_set_microphone_direction(const struct audio_stream_in *stream,
4499 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004500 struct stream_in *in = (struct stream_in *)stream;
4501
4502 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4503
4504 in->direction = dir;
4505
4506 if (in->standby)
4507 return 0;
4508
4509 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004510}
4511
4512static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004513 struct stream_in *in = (struct stream_in *)stream;
4514
4515 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4516
4517 if (zoom > 1.0 || zoom < -1.0)
4518 return -EINVAL;
4519
4520 in->zoom = zoom;
4521
4522 if (in->standby)
4523 return 0;
4524
4525 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004526}
4527
4528
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004529static bool stream_get_parameter_channels(struct str_parms *query,
4530 struct str_parms *reply,
4531 audio_channel_mask_t *supported_channel_masks) {
4532 int ret = -1;
4533 char value[512];
4534 bool first = true;
4535 size_t i, j;
4536
4537 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4538 ret = 0;
4539 value[0] = '\0';
4540 i = 0;
4541 while (supported_channel_masks[i] != 0) {
4542 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4543 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4544 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304545 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004546
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304547 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004548 first = false;
4549 break;
4550 }
4551 }
4552 i++;
4553 }
4554 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4555 }
4556 return ret == 0;
4557}
4558
4559static bool stream_get_parameter_formats(struct str_parms *query,
4560 struct str_parms *reply,
4561 audio_format_t *supported_formats) {
4562 int ret = -1;
4563 char value[256];
4564 size_t i, j;
4565 bool first = true;
4566
4567 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4568 ret = 0;
4569 value[0] = '\0';
4570 i = 0;
4571 while (supported_formats[i] != 0) {
4572 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4573 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4574 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304575 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004576 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304577 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004578 first = false;
4579 break;
4580 }
4581 }
4582 i++;
4583 }
4584 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4585 }
4586 return ret == 0;
4587}
4588
4589static bool stream_get_parameter_rates(struct str_parms *query,
4590 struct str_parms *reply,
4591 uint32_t *supported_sample_rates) {
4592
4593 int i;
4594 char value[256];
4595 int ret = -1;
4596 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4597 ret = 0;
4598 value[0] = '\0';
4599 i=0;
4600 int cursor = 0;
4601 while (supported_sample_rates[i]) {
4602 int avail = sizeof(value) - cursor;
4603 ret = snprintf(value + cursor, avail, "%s%d",
4604 cursor > 0 ? "|" : "",
4605 supported_sample_rates[i]);
4606 if (ret < 0 || ret >= avail) {
4607 // if cursor is at the last element of the array
4608 // overwrite with \0 is duplicate work as
4609 // snprintf already put a \0 in place.
4610 // else
4611 // we had space to write the '|' at value[cursor]
4612 // (which will be overwritten) or no space to fill
4613 // the first element (=> cursor == 0)
4614 value[cursor] = '\0';
4615 break;
4616 }
4617 cursor += ret;
4618 ++i;
4619 }
4620 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4621 value);
4622 }
4623 return ret >= 0;
4624}
4625
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004626static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4627{
4628 struct stream_out *out = (struct stream_out *)stream;
4629 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004630 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004631 char value[256];
4632 struct str_parms *reply = str_parms_create();
4633 size_t i, j;
4634 int ret;
4635 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004636
4637 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004638 if (reply) {
4639 str_parms_destroy(reply);
4640 }
4641 if (query) {
4642 str_parms_destroy(query);
4643 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004644 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4645 return NULL;
4646 }
4647
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004648 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004649 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4650 if (ret >= 0) {
4651 value[0] = '\0';
4652 i = 0;
4653 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004654 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4655 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004656 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004657 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004658 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004659 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004660 first = false;
4661 break;
4662 }
4663 }
4664 i++;
4665 }
4666 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4667 str = str_parms_to_str(reply);
4668 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004669 voice_extn_out_get_parameters(out, query, reply);
4670 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004672
Alexy Joseph62142aa2015-11-16 15:10:34 -08004673
4674 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4675 if (ret >= 0) {
4676 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304677 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4678 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004679 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304680 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004681 } else {
4682 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304683 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004684 }
4685 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004686 if (str)
4687 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004688 str = str_parms_to_str(reply);
4689 }
4690
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004691 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4692 if (ret >= 0) {
4693 value[0] = '\0';
4694 i = 0;
4695 first = true;
4696 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004697 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4698 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004699 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004700 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004701 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004702 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004703 first = false;
4704 break;
4705 }
4706 }
4707 i++;
4708 }
4709 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004710 if (str)
4711 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004712 str = str_parms_to_str(reply);
4713 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004714
4715 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4716 if (ret >= 0) {
4717 value[0] = '\0';
4718 i = 0;
4719 first = true;
4720 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004721 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4722 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004723 if (!first) {
4724 strlcat(value, "|", sizeof(value));
4725 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004726 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004727 first = false;
4728 break;
4729 }
4730 }
4731 i++;
4732 }
4733 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4734 if (str)
4735 free(str);
4736 str = str_parms_to_str(reply);
4737 }
4738
Alexy Joseph98988832017-01-13 14:56:59 -08004739 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4740 //only low latency track supports suspend_resume
4741 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004742 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004743 if (str)
4744 free(str);
4745 str = str_parms_to_str(reply);
4746 }
4747
4748
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004749 str_parms_destroy(query);
4750 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004751 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004752 return str;
4753}
4754
4755static uint32_t out_get_latency(const struct audio_stream_out *stream)
4756{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004757 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004758 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004759 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004760
Alexy Josephaa54c872014-12-03 02:46:47 -08004761 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304762 lock_output_stream(out);
4763 latency = audio_extn_utils_compress_get_dsp_latency(out);
4764 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004765 } else if ((out->realtime) ||
4766 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004767 // since the buffer won't be filled up faster than realtime,
4768 // return a smaller number
4769 if (out->config.rate)
4770 period_ms = (out->af_period_multiplier * out->config.period_size *
4771 1000) / (out->config.rate);
4772 else
4773 period_ms = 0;
4774 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004775 } else {
4776 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004777 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004778 }
4779
yidongh0515e042017-07-06 15:00:34 +08004780 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004781 latency += audio_extn_a2dp_get_encoder_latency();
4782
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304783 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004784 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004785}
4786
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304787static float AmpToDb(float amplification)
4788{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304789 float db = DSD_VOLUME_MIN_DB;
4790 if (amplification > 0) {
4791 db = 20 * log10(amplification);
4792 if(db < DSD_VOLUME_MIN_DB)
4793 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304794 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304795 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304796}
4797
Arun Mirpuri5d170872019-03-26 13:21:31 -07004798static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4799 float right)
4800{
4801 struct stream_out *out = (struct stream_out *)stream;
4802 long volume = 0;
4803 char mixer_ctl_name[128] = "";
4804 struct audio_device *adev = out->dev;
4805 struct mixer_ctl *ctl = NULL;
4806 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4807 PCM_PLAYBACK);
4808
4809 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4810 "Playback %d Volume", pcm_device_id);
4811 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4812 if (!ctl) {
4813 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4814 __func__, mixer_ctl_name);
4815 return -EINVAL;
4816 }
4817 if (left != right)
4818 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4819 __func__, left, right);
4820 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4821 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4822 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4823 __func__, mixer_ctl_name, volume);
4824 return -EINVAL;
4825 }
4826 return 0;
4827}
4828
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304829static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4830 float right)
4831{
4832 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304833 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304834 char mixer_ctl_name[128];
4835 struct audio_device *adev = out->dev;
4836 struct mixer_ctl *ctl;
4837 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4838 PCM_PLAYBACK);
4839
4840 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4841 "Compress Playback %d Volume", pcm_device_id);
4842 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4843 if (!ctl) {
4844 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4845 __func__, mixer_ctl_name);
4846 return -EINVAL;
4847 }
4848 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4849 __func__, mixer_ctl_name, left, right);
4850 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4851 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4852 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4853
4854 return 0;
4855}
4856
Zhou Song2b8f28f2017-09-11 10:51:38 +08004857static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4858 float right)
4859{
4860 struct stream_out *out = (struct stream_out *)stream;
4861 char mixer_ctl_name[] = "App Type Gain";
4862 struct audio_device *adev = out->dev;
4863 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304864 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004865
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07004866 if (!is_valid_volume(left, right)) {
4867 ALOGE("%s: Invalid stream volume for left=%f, right=%f",
4868 __func__, left, right);
4869 return -EINVAL;
4870 }
4871
Zhou Song2b8f28f2017-09-11 10:51:38 +08004872 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4873 if (!ctl) {
4874 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4875 __func__, mixer_ctl_name);
4876 return -EINVAL;
4877 }
4878
4879 set_values[0] = 0; //0: Rx Session 1:Tx Session
4880 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304881 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4882 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004883
4884 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4885 return 0;
4886}
4887
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304888static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4889 float right)
4890{
4891 struct stream_out *out = (struct stream_out *)stream;
4892 /* Volume control for pcm playback */
4893 if (left != right) {
4894 return -EINVAL;
4895 } else {
4896 char mixer_ctl_name[128];
4897 struct audio_device *adev = out->dev;
4898 struct mixer_ctl *ctl;
4899 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4900 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4901 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4902 if (!ctl) {
4903 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4904 return -EINVAL;
4905 }
4906
4907 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4908 int ret = mixer_ctl_set_value(ctl, 0, volume);
4909 if (ret < 0) {
4910 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4911 return -EINVAL;
4912 }
4913
4914 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4915
4916 return 0;
4917 }
4918}
4919
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004920static int out_set_volume(struct audio_stream_out *stream, float left,
4921 float right)
4922{
Eric Laurenta9024de2013-04-04 09:19:12 -07004923 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004924 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304925 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004926
Arun Mirpuri5d170872019-03-26 13:21:31 -07004927 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07004928 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4929 /* only take left channel into account: the API is for stereo anyway */
4930 out->muted = (left == 0.0f);
4931 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004932 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304933 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004934 /*
4935 * Set mute or umute on HDMI passthrough stream.
4936 * Only take left channel into account.
4937 * Mute is 0 and unmute 1
4938 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304939 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304940 } else if (out->format == AUDIO_FORMAT_DSD){
4941 char mixer_ctl_name[128] = "DSD Volume";
4942 struct audio_device *adev = out->dev;
4943 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4944
4945 if (!ctl) {
4946 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4947 __func__, mixer_ctl_name);
4948 return -EINVAL;
4949 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304950 volume[0] = (long)(AmpToDb(left));
4951 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304952 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4953 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004954 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304955 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07004956 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304957 if (!out->a2dp_compress_mute)
4958 ret = out_set_compr_volume(stream, left, right);
4959 out->volume_l = left;
4960 out->volume_r = right;
4961 pthread_mutex_unlock(&out->compr_mute_lock);
4962 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004963 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004964 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004965 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4966 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4967 if (!out->standby) {
4968 audio_extn_utils_send_app_type_gain(out->dev,
4969 out->app_type_cfg.app_type,
4970 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004971 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004972 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004973 out->volume_l = left;
4974 out->volume_r = right;
4975 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07004976 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4977 ALOGV("%s: MMAP set volume called", __func__);
4978 if (!out->standby)
4979 ret = out_set_mmap_volume(stream, left, right);
4980 out->volume_l = left;
4981 out->volume_r = right;
4982 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304983 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304984 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4985 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304986 /* Volume control for pcm playback */
4987 if (!out->standby)
4988 ret = out_set_pcm_volume(stream, left, right);
4989 else
4990 out->apply_volume = true;
4991
4992 out->volume_l = left;
4993 out->volume_r = right;
4994 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004995 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004996
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004997 return -ENOSYS;
4998}
4999
Zhou Songc9672822017-08-16 16:01:39 +08005000static void update_frames_written(struct stream_out *out, size_t bytes)
5001{
5002 size_t bpf = 0;
5003
5004 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
5005 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
5006 bpf = 1;
5007 else if (!is_offload_usecase(out->usecase))
5008 bpf = audio_bytes_per_sample(out->format) *
5009 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08005010
5011 pthread_mutex_lock(&out->position_query_lock);
5012 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08005013 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08005014 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
5015 }
5016 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08005017}
5018
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005019int split_and_write_audio_haptic_data(struct stream_out *out,
5020 const void *buffer, size_t bytes_to_write)
5021{
5022 struct audio_device *adev = out->dev;
5023
5024 int ret = 0;
5025 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5026 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
5027 size_t frame_size = channel_count * bytes_per_sample;
5028 size_t frame_count = bytes_to_write / frame_size;
5029
5030 bool force_haptic_path =
5031 property_get_bool("vendor.audio.test_haptic", false);
5032
5033 // extract Haptics data from Audio buffer
5034 bool alloc_haptic_buffer = false;
5035 int haptic_channel_count = adev->haptics_config.channels;
5036 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
5037 size_t audio_frame_size = frame_size - haptic_frame_size;
5038 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
5039
5040 if (adev->haptic_buffer == NULL) {
5041 alloc_haptic_buffer = true;
5042 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
5043 free(adev->haptic_buffer);
5044 adev->haptic_buffer_size = 0;
5045 alloc_haptic_buffer = true;
5046 }
5047
5048 if (alloc_haptic_buffer) {
5049 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005050 if(adev->haptic_buffer == NULL) {
5051 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5052 return -ENOMEM;
5053 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005054 adev->haptic_buffer_size = total_haptic_buffer_size;
5055 }
5056
5057 size_t src_index = 0, aud_index = 0, hap_index = 0;
5058 uint8_t *audio_buffer = (uint8_t *)buffer;
5059 uint8_t *haptic_buffer = adev->haptic_buffer;
5060
5061 // This is required for testing only. This works for stereo data only.
5062 // One channel is fed to audio stream and other to haptic stream for testing.
5063 if (force_haptic_path)
5064 audio_frame_size = haptic_frame_size = bytes_per_sample;
5065
5066 for (size_t i = 0; i < frame_count; i++) {
5067 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5068 audio_frame_size);
5069 aud_index += audio_frame_size;
5070 src_index += audio_frame_size;
5071
5072 if (adev->haptic_pcm)
5073 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5074 haptic_frame_size);
5075 hap_index += haptic_frame_size;
5076 src_index += haptic_frame_size;
5077
5078 // This is required for testing only.
5079 // Discard haptic channel data.
5080 if (force_haptic_path)
5081 src_index += haptic_frame_size;
5082 }
5083
5084 // write to audio pipeline
5085 ret = pcm_write(out->pcm, (void *)audio_buffer,
5086 frame_count * audio_frame_size);
5087
5088 // write to haptics pipeline
5089 if (adev->haptic_pcm)
5090 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5091 frame_count * haptic_frame_size);
5092
5093 return ret;
5094}
5095
Aalique Grahame22e49102018-12-18 14:23:57 -08005096#ifdef NO_AUDIO_OUT
5097static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5098 const void *buffer __unused, size_t bytes)
5099{
5100 struct stream_out *out = (struct stream_out *)stream;
5101
5102 /* No Output device supported other than BT for playback.
5103 * Sleep for the amount of buffer duration
5104 */
5105 lock_output_stream(out);
5106 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5107 (const struct audio_stream_out *)&out->stream) /
5108 out_get_sample_rate(&out->stream.common));
5109 pthread_mutex_unlock(&out->lock);
5110 return bytes;
5111}
5112#endif
5113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005114static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5115 size_t bytes)
5116{
5117 struct stream_out *out = (struct stream_out *)stream;
5118 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005119 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305120 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005121 const size_t frame_size = audio_stream_out_frame_size(stream);
5122 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305123 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005124
Haynes Mathew George380745d2017-10-04 15:27:45 -07005125 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005126 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305127
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305128 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005129
Dhananjay Kumarac341582017-02-23 23:42:25 +05305130 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305131 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305132 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5133 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005134 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305135 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305136 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305137 ALOGD(" %s: sound card is not active/SSR state", __func__);
5138 ret= -EIO;
5139 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305140 }
5141 }
5142
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305143 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305144 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305145 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305146 goto exit;
5147 }
5148
Haynes Mathew George16081042017-05-31 17:16:49 -07005149 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5150 ret = -EINVAL;
5151 goto exit;
5152 }
5153
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305154 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5155 !out->is_iec61937_info_available) {
5156
5157 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5158 out->is_iec61937_info_available = true;
5159 } else if (audio_extn_passthru_is_enabled()) {
5160 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305161 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305162
5163 if((out->format == AUDIO_FORMAT_DTS) ||
5164 (out->format == AUDIO_FORMAT_DTS_HD)) {
5165 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5166 buffer, bytes);
5167 if (ret) {
5168 if (ret != -ENOSYS) {
5169 out->is_iec61937_info_available = false;
5170 ALOGD("iec61937 transmission info not yet updated retry");
5171 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305172 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305173 /* if stream has started and after that there is
5174 * stream config change (iec transmission config)
5175 * then trigger select_device to update backend configuration.
5176 */
5177 out->stream_config_changed = true;
5178 pthread_mutex_lock(&adev->lock);
5179 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305180 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005181 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305182 ret = -EINVAL;
5183 goto exit;
5184 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305185 pthread_mutex_unlock(&adev->lock);
5186 out->stream_config_changed = false;
5187 out->is_iec61937_info_available = true;
5188 }
5189 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305190
Garmond Leung317cbf12017-09-13 16:20:50 -07005191 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305192 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5193 (out->is_iec61937_info_available == true)) {
5194 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5195 ret = -EINVAL;
5196 goto exit;
5197 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305198 }
5199 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305200
5201 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005202 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005203 if (!(out->devices &
5204 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305205 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305206 ret = -EIO;
5207 goto exit;
5208 }
5209 }
5210 }
5211
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005212 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005213 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005214 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005215 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5216 ret = voice_extn_compress_voip_start_output_stream(out);
5217 else
5218 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005219 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005220 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005221 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005222 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005223 goto exit;
5224 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305225 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005226 if (last_known_cal_step != -1) {
5227 ALOGD("%s: retry previous failed cal level set", __func__);
5228 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305229 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005230 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305231
5232 if ((out->is_iec61937_info_available == true) &&
5233 (audio_extn_passthru_is_passthrough_stream(out))&&
5234 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5235 ret = -EINVAL;
5236 goto exit;
5237 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305238 if (out->set_dual_mono)
5239 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005240 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005241
Ashish Jain81eb2a82015-05-13 10:52:34 +05305242 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005243 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305244 adev->is_channel_status_set = true;
5245 }
5246
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305247 if ((adev->use_old_pspd_mix_ctrl == true) &&
5248 (out->pspd_coeff_sent == false)) {
5249 /*
5250 * Need to resend pspd coefficients after stream started for
5251 * older kernel version as it does not save the coefficients
5252 * and also stream has to be started for coeff to apply.
5253 */
5254 usecase = get_usecase_from_list(adev, out->usecase);
5255 if (usecase != NULL) {
5256 audio_extn_set_custom_mtmx_params(adev, usecase, true);
5257 out->pspd_coeff_sent = true;
5258 }
5259 }
5260
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005261 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005262 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005263 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005264 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005265 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5266 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305267 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5268 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005269 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305270 out->send_next_track_params = false;
5271 out->is_compr_metadata_avail = false;
5272 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005273 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305274 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305275 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005276
Ashish Jain83a6cc22016-06-28 14:34:17 +05305277 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305278 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305279 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305280 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005281 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305282 return -EINVAL;
5283 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305284 audio_format_t dst_format = out->hal_op_format;
5285 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305286
Dieter Luecking5d57def2018-09-07 14:23:37 +02005287 /* prevent division-by-zero */
5288 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5289 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5290 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5291 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305292 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005293 ATRACE_END();
5294 return -EINVAL;
5295 }
5296
Ashish Jainf1eaa582016-05-23 20:54:24 +05305297 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5298 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5299
Ashish Jain83a6cc22016-06-28 14:34:17 +05305300 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305301 dst_format,
5302 buffer,
5303 src_format,
5304 frames);
5305
Ashish Jain83a6cc22016-06-28 14:34:17 +05305306 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305307 bytes_to_write);
5308
5309 /*Convert written bytes in audio flinger format*/
5310 if (ret > 0)
5311 ret = ((ret * format_to_bitwidth_table[out->format]) /
5312 format_to_bitwidth_table[dst_format]);
5313 }
5314 } else
5315 ret = compress_write(out->compr, buffer, bytes);
5316
Zhou Songc9672822017-08-16 16:01:39 +08005317 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5318 update_frames_written(out, bytes);
5319
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305320 if (ret < 0)
5321 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005322 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305323 /*msg to cb thread only if non blocking write is enabled*/
5324 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305325 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005326 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305327 } else if (-ENETRESET == ret) {
5328 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305329 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305330 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305331 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005332 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305333 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005334 }
Ashish Jain5106d362016-05-11 19:23:33 +05305335
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305336 /* Call compr start only when non-zero bytes of data is there to be rendered */
5337 if (!out->playback_started && ret > 0) {
5338 int status = compress_start(out->compr);
5339 if (status < 0) {
5340 ret = status;
5341 ALOGE("%s: compr start failed with err %d", __func__, errno);
5342 goto exit;
5343 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005344 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005345 out->playback_started = 1;
5346 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005347
5348 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5349 popcount(out->channel_mask),
5350 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005351 }
5352 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005353 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005354 return ret;
5355 } else {
5356 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005357 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005358 if (out->muted)
5359 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005360 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5361 __func__, frames, frame_size, bytes_to_write);
5362
Aalique Grahame22e49102018-12-18 14:23:57 -08005363 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005364 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5365 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5366 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005367 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5368 int16_t *src = (int16_t *)buffer;
5369 int16_t *dst = (int16_t *)buffer;
5370
5371 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5372 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005373 "out_write called for %s use case with wrong properties",
5374 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005375
5376 /*
5377 * FIXME: this can be removed once audio flinger mixer supports
5378 * mono output
5379 */
5380
5381 /*
5382 * Code below goes over each frame in the buffer and adds both
5383 * L and R samples and then divides by 2 to convert to mono
5384 */
5385 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5386 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5387 }
5388 bytes_to_write /= 2;
5389 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005390
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305391 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005392
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005393 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005394
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005395 if (out->config.rate)
5396 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5397 out->config.rate;
5398
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005399 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005400 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5401
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005402 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005403 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005404 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305405 out->convert_buffer != NULL) {
5406
5407 memcpy_by_audio_format(out->convert_buffer,
5408 out->hal_op_format,
5409 buffer,
5410 out->hal_ip_format,
5411 out->config.period_size * out->config.channels);
5412
5413 ret = pcm_write(out->pcm, out->convert_buffer,
5414 (out->config.period_size *
5415 out->config.channels *
5416 format_to_bitwidth_table[out->hal_op_format]));
5417 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305418 /*
5419 * To avoid underrun in DSP when the application is not pumping
5420 * data at required rate, check for the no. of bytes and ignore
5421 * pcm_write if it is less than actual buffer size.
5422 * It is a work around to a change in compress VOIP driver.
5423 */
5424 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5425 bytes < (out->config.period_size * out->config.channels *
5426 audio_bytes_per_sample(out->format))) {
5427 size_t voip_buf_size =
5428 out->config.period_size * out->config.channels *
5429 audio_bytes_per_sample(out->format);
5430 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5431 __func__, bytes, voip_buf_size);
5432 usleep(((uint64_t)voip_buf_size - bytes) *
5433 1000000 / audio_stream_out_frame_size(stream) /
5434 out_get_sample_rate(&out->stream.common));
5435 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005436 } else {
5437 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5438 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5439 else
5440 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5441 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305442 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005443
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005444 release_out_focus(out);
5445
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305446 if (ret < 0)
5447 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005448 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305449 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005450 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005451 }
5452
5453exit:
Zhou Songc9672822017-08-16 16:01:39 +08005454 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305455 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305456 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305457 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005458 pthread_mutex_unlock(&out->lock);
5459
5460 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005461 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005462 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305463 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305464 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305465 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305466 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305467 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305468 out->standby = true;
5469 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305470 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005471 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5472 /* prevent division-by-zero */
5473 uint32_t stream_size = audio_stream_out_frame_size(stream);
5474 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005475
Dieter Luecking5d57def2018-09-07 14:23:37 +02005476 if ((stream_size == 0) || (srate == 0)) {
5477 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5478 ATRACE_END();
5479 return -EINVAL;
5480 }
5481 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5482 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005483 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305484 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005485 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005486 return ret;
5487 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005488 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005489 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005490 return bytes;
5491}
5492
5493static int out_get_render_position(const struct audio_stream_out *stream,
5494 uint32_t *dsp_frames)
5495{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005496 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005497
5498 if (dsp_frames == NULL)
5499 return -EINVAL;
5500
5501 *dsp_frames = 0;
5502 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005503 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305504
5505 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5506 * this operation and adev_close_output_stream(where out gets reset).
5507 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305508 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005509 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305510 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005511 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305512 return 0;
5513 }
5514
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005515 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305516 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305517 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005518 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305519 if (ret < 0)
5520 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005521 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305522 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005523 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305524 if (-ENETRESET == ret) {
5525 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305526 out->card_status = CARD_STATUS_OFFLINE;
5527 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305528 } else if(ret < 0) {
5529 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305530 ret = -EINVAL;
5531 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305532 /*
5533 * Handle corner case where compress session is closed during SSR
5534 * and timestamp is queried
5535 */
5536 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305537 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305538 } else if (out->prev_card_status_offline) {
5539 ALOGE("ERROR: previously sound card was offline,return error");
5540 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305541 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305542 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005543 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305544 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305545 pthread_mutex_unlock(&out->lock);
5546 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005547 } else if (audio_is_linear_pcm(out->format)) {
5548 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005549 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005550 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005551 } else
5552 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005553}
5554
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005555static int out_add_audio_effect(const struct audio_stream *stream __unused,
5556 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005557{
5558 return 0;
5559}
5560
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005561static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5562 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005563{
5564 return 0;
5565}
5566
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005567static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5568 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005569{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305570 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005571}
5572
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005573static int out_get_presentation_position(const struct audio_stream_out *stream,
5574 uint64_t *frames, struct timespec *timestamp)
5575{
5576 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305577 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005578 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005579
Ashish Jain5106d362016-05-11 19:23:33 +05305580 /* below piece of code is not guarded against any lock because audioFliner serializes
5581 * this operation and adev_close_output_stream( where out gets reset).
5582 */
5583 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305584 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005585 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305586 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5587 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5588 return 0;
5589 }
5590
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005591 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005592
Ashish Jain5106d362016-05-11 19:23:33 +05305593 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5594 ret = compress_get_tstamp(out->compr, &dsp_frames,
5595 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005596 // Adjustment accounts for A2dp encoder latency with offload usecases
5597 // Note: Encoder latency is returned in ms.
5598 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5599 unsigned long offset =
5600 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5601 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5602 }
Ashish Jain5106d362016-05-11 19:23:33 +05305603 ALOGVV("%s rendered frames %ld sample_rate %d",
5604 __func__, dsp_frames, out->sample_rate);
5605 *frames = dsp_frames;
5606 if (ret < 0)
5607 ret = -errno;
5608 if (-ENETRESET == ret) {
5609 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305610 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305611 ret = -EINVAL;
5612 } else
5613 ret = 0;
5614 /* this is the best we can do */
5615 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005616 } else {
5617 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005618 unsigned int avail;
5619 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5620 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5621 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5622 // This adjustment accounts for buffering after app processor.
5623 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005624 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005625 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005626
Weiyin Jiangd4633762018-03-16 12:05:03 +08005627 // Adjustment accounts for A2dp encoder latency with non offload usecases
5628 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5629 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5630 signed_frames -=
5631 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5632 }
5633
5634 // It would be unusual for this value to be negative, but check just in case ...
5635 if (signed_frames >= 0) {
5636 *frames = signed_frames;
5637 ret = 0;
5638 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005639 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305640 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305641 *frames = out->written;
5642 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305643 if (is_offload_usecase(out->usecase))
5644 ret = -EINVAL;
5645 else
5646 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005647 }
5648 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005649 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005650 return ret;
5651}
5652
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005653static int out_set_callback(struct audio_stream_out *stream,
5654 stream_callback_t callback, void *cookie)
5655{
5656 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005657 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005658
5659 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005660 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005661 out->client_callback = callback;
5662 out->client_cookie = cookie;
5663 if (out->adsp_hdlr_stream_handle) {
5664 ret = audio_extn_adsp_hdlr_stream_set_callback(
5665 out->adsp_hdlr_stream_handle,
5666 callback,
5667 cookie);
5668 if (ret)
5669 ALOGW("%s:adsp hdlr callback registration failed %d",
5670 __func__, ret);
5671 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005672 pthread_mutex_unlock(&out->lock);
5673 return 0;
5674}
5675
5676static int out_pause(struct audio_stream_out* stream)
5677{
5678 struct stream_out *out = (struct stream_out *)stream;
5679 int status = -ENOSYS;
5680 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005681 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005682 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005683 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005684 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305685 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305686 status = compress_pause(out->compr);
5687
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005688 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005689
Mingming Yin21854652016-04-13 11:54:02 -07005690 if (audio_extn_passthru_is_active()) {
5691 ALOGV("offload use case, pause passthru");
5692 audio_extn_passthru_on_pause(out);
5693 }
5694
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305695 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005696 audio_extn_dts_notify_playback_state(out->usecase, 0,
5697 out->sample_rate, popcount(out->channel_mask),
5698 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005699 }
5700 pthread_mutex_unlock(&out->lock);
5701 }
5702 return status;
5703}
5704
5705static int out_resume(struct audio_stream_out* stream)
5706{
5707 struct stream_out *out = (struct stream_out *)stream;
5708 int status = -ENOSYS;
5709 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005710 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005711 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005712 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005713 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005714 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305715 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305716 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005717 }
5718 if (!status) {
5719 out->offload_state = OFFLOAD_STATE_PLAYING;
5720 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305721 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005722 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5723 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005724 }
5725 pthread_mutex_unlock(&out->lock);
5726 }
5727 return status;
5728}
5729
5730static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5731{
5732 struct stream_out *out = (struct stream_out *)stream;
5733 int status = -ENOSYS;
5734 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005735 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005736 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005737 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5738 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5739 else
5740 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5741 pthread_mutex_unlock(&out->lock);
5742 }
5743 return status;
5744}
5745
5746static int out_flush(struct audio_stream_out* stream)
5747{
5748 struct stream_out *out = (struct stream_out *)stream;
5749 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005750 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005751 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005752 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005753 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5754 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005755 } else {
5756 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5757 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005758 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005759 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005760 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005761 return 0;
5762 }
5763 return -ENOSYS;
5764}
5765
Haynes Mathew George16081042017-05-31 17:16:49 -07005766static int out_stop(const struct audio_stream_out* stream)
5767{
5768 struct stream_out *out = (struct stream_out *)stream;
5769 struct audio_device *adev = out->dev;
5770 int ret = -ENOSYS;
5771
5772 ALOGV("%s", __func__);
5773 pthread_mutex_lock(&adev->lock);
5774 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5775 out->playback_started && out->pcm != NULL) {
5776 pcm_stop(out->pcm);
5777 ret = stop_output_stream(out);
5778 out->playback_started = false;
5779 }
5780 pthread_mutex_unlock(&adev->lock);
5781 return ret;
5782}
5783
5784static int out_start(const struct audio_stream_out* stream)
5785{
5786 struct stream_out *out = (struct stream_out *)stream;
5787 struct audio_device *adev = out->dev;
5788 int ret = -ENOSYS;
5789
5790 ALOGV("%s", __func__);
5791 pthread_mutex_lock(&adev->lock);
5792 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5793 !out->playback_started && out->pcm != NULL) {
5794 ret = start_output_stream(out);
5795 if (ret == 0) {
5796 out->playback_started = true;
5797 }
5798 }
5799 pthread_mutex_unlock(&adev->lock);
5800 return ret;
5801}
5802
5803/*
5804 * Modify config->period_count based on min_size_frames
5805 */
5806static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5807{
5808 int periodCountRequested = (min_size_frames + config->period_size - 1)
5809 / config->period_size;
5810 int periodCount = MMAP_PERIOD_COUNT_MIN;
5811
5812 ALOGV("%s original config.period_size = %d config.period_count = %d",
5813 __func__, config->period_size, config->period_count);
5814
5815 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5816 periodCount *= 2;
5817 }
5818 config->period_count = periodCount;
5819
5820 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5821}
5822
Phil Burkfe17efd2019-03-25 10:23:35 -07005823// Read offset for the positional timestamp from a persistent vendor property.
5824// This is to workaround apparent inaccuracies in the timing information that
5825// is used by the AAudio timing model. The inaccuracies can cause glitches.
5826static int64_t get_mmap_out_time_offset() {
5827 const int32_t kDefaultOffsetMicros = 0;
5828 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08005829 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07005830 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
5831 return mmap_time_offset_micros * (int64_t)1000;
5832}
5833
Haynes Mathew George16081042017-05-31 17:16:49 -07005834static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5835 int32_t min_size_frames,
5836 struct audio_mmap_buffer_info *info)
5837{
5838 struct stream_out *out = (struct stream_out *)stream;
5839 struct audio_device *adev = out->dev;
5840 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005841 unsigned int offset1 = 0;
5842 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005843 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005844 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005845 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005846
Arun Mirpuri5d170872019-03-26 13:21:31 -07005847 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305848 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005849 pthread_mutex_lock(&adev->lock);
5850
Sharad Sanglec6f32552018-05-04 16:15:38 +05305851 if (CARD_STATUS_OFFLINE == out->card_status ||
5852 CARD_STATUS_OFFLINE == adev->card_status) {
5853 ALOGW("out->card_status or adev->card_status offline, try again");
5854 ret = -EIO;
5855 goto exit;
5856 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005857 if (info == NULL || min_size_frames == 0) {
5858 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5859 ret = -EINVAL;
5860 goto exit;
5861 }
5862 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5863 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5864 ret = -ENOSYS;
5865 goto exit;
5866 }
5867 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5868 if (out->pcm_device_id < 0) {
5869 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5870 __func__, out->pcm_device_id, out->usecase);
5871 ret = -EINVAL;
5872 goto exit;
5873 }
5874
5875 adjust_mmap_period_count(&out->config, min_size_frames);
5876
Arun Mirpuri5d170872019-03-26 13:21:31 -07005877 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005878 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5879 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5880 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305881 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305882 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5883 out->card_status = CARD_STATUS_OFFLINE;
5884 adev->card_status = CARD_STATUS_OFFLINE;
5885 ret = -EIO;
5886 goto exit;
5887 }
5888
Haynes Mathew George16081042017-05-31 17:16:49 -07005889 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5890 step = "open";
5891 ret = -ENODEV;
5892 goto exit;
5893 }
5894 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5895 if (ret < 0) {
5896 step = "begin";
5897 goto exit;
5898 }
5899 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005900 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005901 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005902 ret = platform_get_mmap_data_fd(adev->platform,
5903 out->pcm_device_id, 0 /*playback*/,
5904 &info->shared_memory_fd,
5905 &mmap_size);
5906 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005907 // Fall back to non exclusive mode
5908 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5909 } else {
5910 if (mmap_size < buffer_size) {
5911 step = "mmap";
5912 goto exit;
5913 }
5914 // FIXME: indicate exclusive mode support by returning a negative buffer size
5915 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005916 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005917 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005918 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005919
5920 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5921 if (ret < 0) {
5922 step = "commit";
5923 goto exit;
5924 }
5925
Phil Burkfe17efd2019-03-25 10:23:35 -07005926 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
5927
Haynes Mathew George16081042017-05-31 17:16:49 -07005928 out->standby = false;
5929 ret = 0;
5930
Arun Mirpuri5d170872019-03-26 13:21:31 -07005931 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005932 __func__, info->shared_memory_address, info->buffer_size_frames);
5933
5934exit:
5935 if (ret != 0) {
5936 if (out->pcm == NULL) {
5937 ALOGE("%s: %s - %d", __func__, step, ret);
5938 } else {
5939 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5940 pcm_close(out->pcm);
5941 out->pcm = NULL;
5942 }
5943 }
5944 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305945 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005946 return ret;
5947}
5948
5949static int out_get_mmap_position(const struct audio_stream_out *stream,
5950 struct audio_mmap_position *position)
5951{
5952 struct stream_out *out = (struct stream_out *)stream;
5953 ALOGVV("%s", __func__);
5954 if (position == NULL) {
5955 return -EINVAL;
5956 }
5957 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005958 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005959 return -ENOSYS;
5960 }
5961 if (out->pcm == NULL) {
5962 return -ENOSYS;
5963 }
5964
5965 struct timespec ts = { 0, 0 };
5966 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5967 if (ret < 0) {
5968 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5969 return ret;
5970 }
Phil Burkfe17efd2019-03-25 10:23:35 -07005971 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
5972 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07005973 return 0;
5974}
5975
5976
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005977/** audio_stream_in implementation **/
5978static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5979{
5980 struct stream_in *in = (struct stream_in *)stream;
5981
5982 return in->config.rate;
5983}
5984
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005985static int in_set_sample_rate(struct audio_stream *stream __unused,
5986 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005987{
5988 return -ENOSYS;
5989}
5990
5991static size_t in_get_buffer_size(const struct audio_stream *stream)
5992{
5993 struct stream_in *in = (struct stream_in *)stream;
5994
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005995 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5996 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005997 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5998 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 -07005999 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
6000 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306001 else if(audio_extn_cin_attached_usecase(in->usecase))
6002 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006003
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006004 return in->config.period_size * in->af_period_multiplier *
6005 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006006}
6007
6008static uint32_t in_get_channels(const struct audio_stream *stream)
6009{
6010 struct stream_in *in = (struct stream_in *)stream;
6011
6012 return in->channel_mask;
6013}
6014
6015static audio_format_t in_get_format(const struct audio_stream *stream)
6016{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006017 struct stream_in *in = (struct stream_in *)stream;
6018
6019 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006020}
6021
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006022static int in_set_format(struct audio_stream *stream __unused,
6023 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006024{
6025 return -ENOSYS;
6026}
6027
6028static int in_standby(struct audio_stream *stream)
6029{
6030 struct stream_in *in = (struct stream_in *)stream;
6031 struct audio_device *adev = in->dev;
6032 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306033 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
6034 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07006035 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306036
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006037 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006038 if (!in->standby && in->is_st_session) {
6039 ALOGD("%s: sound trigger pcm stop lab", __func__);
6040 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08006041 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006042 in->standby = 1;
6043 }
6044
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006045 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006046 if (adev->adm_deregister_stream)
6047 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6048
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006049 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006050 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006051 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006052 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006053 voice_extn_compress_voip_close_input_stream(stream);
6054 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006055 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6056 do_stop = in->capture_started;
6057 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006058 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306059 if (audio_extn_cin_attached_usecase(in->usecase))
6060 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006061 }
6062
Arun Mirpuri5d170872019-03-26 13:21:31 -07006063 if (in->pcm) {
6064 ATRACE_BEGIN("pcm_in_close");
6065 pcm_close(in->pcm);
6066 ATRACE_END();
6067 in->pcm = NULL;
6068 }
6069
6070 if(do_stop) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006071 adev->enable_voicerx = false;
6072 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08006073 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006074 }
Quinn Malef6050362019-01-30 15:55:40 -08006075
6076 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6077 adev->num_va_sessions--;
6078
Eric Laurent150dbfe2013-02-27 14:31:02 -08006079 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006080 }
6081 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006082 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006083 return status;
6084}
6085
Aalique Grahame22e49102018-12-18 14:23:57 -08006086static int in_dump(const struct audio_stream *stream,
6087 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006088{
Aalique Grahame22e49102018-12-18 14:23:57 -08006089 struct stream_in *in = (struct stream_in *)stream;
6090
6091 // We try to get the lock for consistency,
6092 // but it isn't necessary for these variables.
6093 // If we're not in standby, we may be blocked on a read.
6094 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6095 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6096 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6097 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6098
6099 if (locked) {
6100 pthread_mutex_unlock(&in->lock);
6101 }
6102
6103 // dump error info
6104 (void)error_log_dump(
6105 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6106
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006107 return 0;
6108}
6109
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306110static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6111{
6112 if (!stream || !parms)
6113 return;
6114
6115 struct stream_in *in = (struct stream_in *)stream;
6116 struct audio_device *adev = in->dev;
6117
6118 card_status_t status;
6119 int card;
6120 if (parse_snd_card_status(parms, &card, &status) < 0)
6121 return;
6122
6123 pthread_mutex_lock(&adev->lock);
6124 bool valid_cb = (card == adev->snd_card);
6125 pthread_mutex_unlock(&adev->lock);
6126
6127 if (!valid_cb)
6128 return;
6129
6130 lock_input_stream(in);
6131 if (in->card_status != status)
6132 in->card_status = status;
6133 pthread_mutex_unlock(&in->lock);
6134
6135 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6136 use_case_table[in->usecase],
6137 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6138
6139 // a better solution would be to report error back to AF and let
6140 // it put the stream to standby
6141 if (status == CARD_STATUS_OFFLINE)
6142 in_standby(&in->stream.common);
6143
6144 return;
6145}
6146
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006147static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6148{
6149 struct stream_in *in = (struct stream_in *)stream;
6150 struct audio_device *adev = in->dev;
6151 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006152 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006153 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006154
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306155 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006156 parms = str_parms_create_str(kvpairs);
6157
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306158 if (!parms)
6159 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006160 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006161 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006162
6163 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6164 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006165 val = atoi(value);
6166 /* no audio source uses val == 0 */
6167 if ((in->source != val) && (val != 0)) {
6168 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006169 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6170 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6171 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006172 (in->config.rate == 8000 || in->config.rate == 16000 ||
6173 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006174 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006175 err = voice_extn_compress_voip_open_input_stream(in);
6176 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006177 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006178 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006179 }
6180 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006181 }
6182 }
6183
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006184 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6185 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006186 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006187 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6188
6189 // Workaround: If routing to an non existing usb device, fail gracefully
6190 // The routing request will otherwise block during 10 second
6191 int card;
6192 if (audio_is_usb_in_device(val) &&
6193 (card = get_alive_usb_card(parms)) >= 0) {
6194
6195 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6196 ret = -ENOSYS;
6197 } else {
6198
6199 in->device = val;
6200 /* If recording is in progress, change the tx device to new device */
6201 if (!in->standby && !in->is_st_session) {
6202 ALOGV("update input routing change");
6203 // inform adm before actual routing to prevent glitches.
6204 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006205 adev->adm_on_routing_change(adev->adm_data,
6206 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006207 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006208 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6209 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006210 }
6211 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006212 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006213 }
6214 }
6215
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306216 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6217 if (err >= 0) {
6218 strlcpy(in->profile, value, sizeof(in->profile));
6219 ALOGV("updating stream profile with value '%s'", in->profile);
6220 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6221 &adev->streams_input_cfg_list,
6222 in->device, in->flags, in->format,
6223 in->sample_rate, in->bit_width,
6224 in->profile, &in->app_type_cfg);
6225 }
6226
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006227 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006228 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006229
6230 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306231error:
Eric Laurent994a6932013-07-17 11:51:42 -07006232 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006233 return ret;
6234}
6235
6236static char* in_get_parameters(const struct audio_stream *stream,
6237 const char *keys)
6238{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006239 struct stream_in *in = (struct stream_in *)stream;
6240 struct str_parms *query = str_parms_create_str(keys);
6241 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006242 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006243
6244 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006245 if (reply) {
6246 str_parms_destroy(reply);
6247 }
6248 if (query) {
6249 str_parms_destroy(query);
6250 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006251 ALOGE("in_get_parameters: failed to create query or reply");
6252 return NULL;
6253 }
6254
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006255 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006256
6257 voice_extn_in_get_parameters(in, query, reply);
6258
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006259 stream_get_parameter_channels(query, reply,
6260 &in->supported_channel_masks[0]);
6261 stream_get_parameter_formats(query, reply,
6262 &in->supported_formats[0]);
6263 stream_get_parameter_rates(query, reply,
6264 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006265 str = str_parms_to_str(reply);
6266 str_parms_destroy(query);
6267 str_parms_destroy(reply);
6268
6269 ALOGV("%s: exit: returns - %s", __func__, str);
6270 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006271}
6272
Aalique Grahame22e49102018-12-18 14:23:57 -08006273static int in_set_gain(struct audio_stream_in *stream,
6274 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006275{
Aalique Grahame22e49102018-12-18 14:23:57 -08006276 struct stream_in *in = (struct stream_in *)stream;
6277 char mixer_ctl_name[128];
6278 struct mixer_ctl *ctl;
6279 int ctl_value;
6280
6281 ALOGV("%s: gain %f", __func__, gain);
6282
6283 if (stream == NULL)
6284 return -EINVAL;
6285
6286 /* in_set_gain() only used to silence MMAP capture for now */
6287 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6288 return -ENOSYS;
6289
6290 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6291
6292 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6293 if (!ctl) {
6294 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6295 __func__, mixer_ctl_name);
6296 return -ENOSYS;
6297 }
6298
6299 if (gain < RECORD_GAIN_MIN)
6300 gain = RECORD_GAIN_MIN;
6301 else if (gain > RECORD_GAIN_MAX)
6302 gain = RECORD_GAIN_MAX;
6303 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6304
6305 mixer_ctl_set_value(ctl, 0, ctl_value);
6306
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006307 return 0;
6308}
6309
6310static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6311 size_t bytes)
6312{
6313 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306314
6315 if (in == NULL) {
6316 ALOGE("%s: stream_in ptr is NULL", __func__);
6317 return -EINVAL;
6318 }
6319
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006320 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306321 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306322 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006323
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006324 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306325
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006326 if (in->is_st_session) {
6327 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6328 /* Read from sound trigger HAL */
6329 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006330 if (in->standby) {
6331 adev->num_va_sessions++;
6332 in->standby = 0;
6333 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006334 pthread_mutex_unlock(&in->lock);
6335 return bytes;
6336 }
6337
Haynes Mathew George16081042017-05-31 17:16:49 -07006338 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6339 ret = -ENOSYS;
6340 goto exit;
6341 }
6342
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006343 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6344 !in->standby && adev->adm_routing_changed) {
6345 ret = -ENOSYS;
6346 goto exit;
6347 }
6348
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006349 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006350 pthread_mutex_lock(&adev->lock);
6351 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6352 ret = voice_extn_compress_voip_start_input_stream(in);
6353 else
6354 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006355 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6356 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006357 pthread_mutex_unlock(&adev->lock);
6358 if (ret != 0) {
6359 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006360 }
6361 in->standby = 0;
6362 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006363
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006364 // what's the duration requested by the client?
6365 long ns = 0;
6366
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306367 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006368 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6369 in->config.rate;
6370
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006371 ret = request_in_focus(in, ns);
6372 if (ret != 0)
6373 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006374 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006375
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306376 if (audio_extn_cin_attached_usecase(in->usecase)) {
6377 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6378 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306379 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006380 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306381 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006382 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006383 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006384 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006385 } else if (audio_extn_ffv_get_stream() == in) {
6386 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306387 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006388 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306389 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6390 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6391 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6392 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306393 ret = -EINVAL;
6394 goto exit;
6395 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306396 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306397 ret = -errno;
6398 }
6399 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306400 /* bytes read is always set to bytes for non compress usecases */
6401 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006402 }
6403
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006404 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006405
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006406 /*
Quinn Malef6050362019-01-30 15:55:40 -08006407 * Instead of writing zeroes here, we could trust the hardware to always
6408 * provide zeroes when muted. This is also muted with voice recognition
6409 * usecases so that other clients do not have access to voice recognition
6410 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006411 */
Quinn Malef6050362019-01-30 15:55:40 -08006412 if ((ret == 0 && voice_get_mic_mute(adev) &&
6413 !voice_is_in_call_rec_stream(in) &&
6414 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6415 (adev->num_va_sessions &&
6416 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6417 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6418 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006419 memset(buffer, 0, bytes);
6420
6421exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306422 frame_size = audio_stream_in_frame_size(stream);
6423 if (frame_size > 0)
6424 in->frames_read += bytes_read/frame_size;
6425
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006426 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306427 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006428 pthread_mutex_unlock(&in->lock);
6429
6430 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306431 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306432 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306433 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306434 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306435 in->standby = true;
6436 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306437 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6438 bytes_read = bytes;
6439 memset(buffer, 0, bytes);
6440 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006441 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006442 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6443 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006444 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306445 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306446 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006447 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306448 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006449}
6450
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006451static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006452{
6453 return 0;
6454}
6455
Aalique Grahame22e49102018-12-18 14:23:57 -08006456static int in_get_capture_position(const struct audio_stream_in *stream,
6457 int64_t *frames, int64_t *time)
6458{
6459 if (stream == NULL || frames == NULL || time == NULL) {
6460 return -EINVAL;
6461 }
6462 struct stream_in *in = (struct stream_in *)stream;
6463 int ret = -ENOSYS;
6464
6465 lock_input_stream(in);
6466 // note: ST sessions do not close the alsa pcm driver synchronously
6467 // on standby. Therefore, we may return an error even though the
6468 // pcm stream is still opened.
6469 if (in->standby) {
6470 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6471 "%s stream in standby but pcm not NULL for non ST session", __func__);
6472 goto exit;
6473 }
6474 if (in->pcm) {
6475 struct timespec timestamp;
6476 unsigned int avail;
6477 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6478 *frames = in->frames_read + avail;
6479 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6480 ret = 0;
6481 }
6482 }
6483exit:
6484 pthread_mutex_unlock(&in->lock);
6485 return ret;
6486}
6487
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006488static int add_remove_audio_effect(const struct audio_stream *stream,
6489 effect_handle_t effect,
6490 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006491{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006492 struct stream_in *in = (struct stream_in *)stream;
6493 int status = 0;
6494 effect_descriptor_t desc;
6495
6496 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006497 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6498
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006499 if (status != 0)
6500 return status;
6501
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006502 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006503 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006504 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006505 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006506 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006507 in->enable_aec != enable &&
6508 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6509 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006510 if (!enable)
6511 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6512 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6513 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6514 in->dev->enable_voicerx = enable;
6515 struct audio_usecase *usecase;
6516 struct listnode *node;
6517 list_for_each(node, &in->dev->usecase_list) {
6518 usecase = node_to_item(node, struct audio_usecase, list);
6519 if (usecase->type == PCM_PLAYBACK)
6520 select_devices(in->dev, usecase->id);
6521 }
6522 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006523 if (!in->standby) {
6524 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6525 select_devices(in->dev, in->usecase);
6526 }
6527
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006528 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006529 if (in->enable_ns != enable &&
6530 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6531 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006532 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006533 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6534 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006535 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6536 select_devices(in->dev, in->usecase);
6537 } else
6538 select_devices(in->dev, in->usecase);
6539 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006540 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006541 pthread_mutex_unlock(&in->dev->lock);
6542 pthread_mutex_unlock(&in->lock);
6543
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006544 return 0;
6545}
6546
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006547static int in_add_audio_effect(const struct audio_stream *stream,
6548 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006549{
Eric Laurent994a6932013-07-17 11:51:42 -07006550 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006551 return add_remove_audio_effect(stream, effect, true);
6552}
6553
6554static int in_remove_audio_effect(const struct audio_stream *stream,
6555 effect_handle_t effect)
6556{
Eric Laurent994a6932013-07-17 11:51:42 -07006557 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006558 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006559}
6560
Derek Chenf939fb72018-11-13 13:34:41 -08006561streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6562 audio_io_handle_t input)
6563{
6564 struct listnode *node;
6565
6566 list_for_each(node, &dev->active_inputs_list) {
6567 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6568 streams_input_ctxt_t,
6569 list);
6570 if (in_ctxt->input->capture_handle == input) {
6571 return in_ctxt;
6572 }
6573 }
6574 return NULL;
6575}
6576
6577streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6578 audio_io_handle_t output)
6579{
6580 struct listnode *node;
6581
6582 list_for_each(node, &dev->active_outputs_list) {
6583 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6584 streams_output_ctxt_t,
6585 list);
6586 if (out_ctxt->output->handle == output) {
6587 return out_ctxt;
6588 }
6589 }
6590 return NULL;
6591}
6592
Haynes Mathew George16081042017-05-31 17:16:49 -07006593static int in_stop(const struct audio_stream_in* stream)
6594{
6595 struct stream_in *in = (struct stream_in *)stream;
6596 struct audio_device *adev = in->dev;
6597
6598 int ret = -ENOSYS;
6599 ALOGV("%s", __func__);
6600 pthread_mutex_lock(&adev->lock);
6601 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6602 in->capture_started && in->pcm != NULL) {
6603 pcm_stop(in->pcm);
6604 ret = stop_input_stream(in);
6605 in->capture_started = false;
6606 }
6607 pthread_mutex_unlock(&adev->lock);
6608 return ret;
6609}
6610
6611static int in_start(const struct audio_stream_in* stream)
6612{
6613 struct stream_in *in = (struct stream_in *)stream;
6614 struct audio_device *adev = in->dev;
6615 int ret = -ENOSYS;
6616
6617 ALOGV("%s in %p", __func__, in);
6618 pthread_mutex_lock(&adev->lock);
6619 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6620 !in->capture_started && in->pcm != NULL) {
6621 if (!in->capture_started) {
6622 ret = start_input_stream(in);
6623 if (ret == 0) {
6624 in->capture_started = true;
6625 }
6626 }
6627 }
6628 pthread_mutex_unlock(&adev->lock);
6629 return ret;
6630}
6631
Phil Burke0a86d12019-02-16 22:28:11 -08006632// Read offset for the positional timestamp from a persistent vendor property.
6633// This is to workaround apparent inaccuracies in the timing information that
6634// is used by the AAudio timing model. The inaccuracies can cause glitches.
6635static int64_t in_get_mmap_time_offset() {
6636 const int32_t kDefaultOffsetMicros = 0;
6637 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006638 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006639 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6640 return mmap_time_offset_micros * (int64_t)1000;
6641}
6642
Haynes Mathew George16081042017-05-31 17:16:49 -07006643static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6644 int32_t min_size_frames,
6645 struct audio_mmap_buffer_info *info)
6646{
6647 struct stream_in *in = (struct stream_in *)stream;
6648 struct audio_device *adev = in->dev;
6649 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006650 unsigned int offset1 = 0;
6651 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006652 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006653 uint32_t mmap_size = 0;
6654 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006655
6656 pthread_mutex_lock(&adev->lock);
6657 ALOGV("%s in %p", __func__, in);
6658
Sharad Sanglec6f32552018-05-04 16:15:38 +05306659 if (CARD_STATUS_OFFLINE == in->card_status||
6660 CARD_STATUS_OFFLINE == adev->card_status) {
6661 ALOGW("in->card_status or adev->card_status offline, try again");
6662 ret = -EIO;
6663 goto exit;
6664 }
6665
Haynes Mathew George16081042017-05-31 17:16:49 -07006666 if (info == NULL || min_size_frames == 0) {
6667 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6668 ret = -EINVAL;
6669 goto exit;
6670 }
6671 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6672 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6673 ALOGV("%s in %p", __func__, in);
6674 ret = -ENOSYS;
6675 goto exit;
6676 }
6677 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6678 if (in->pcm_device_id < 0) {
6679 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6680 __func__, in->pcm_device_id, in->usecase);
6681 ret = -EINVAL;
6682 goto exit;
6683 }
6684
6685 adjust_mmap_period_count(&in->config, min_size_frames);
6686
6687 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6688 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6689 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6690 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306691 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306692 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6693 in->card_status = CARD_STATUS_OFFLINE;
6694 adev->card_status = CARD_STATUS_OFFLINE;
6695 ret = -EIO;
6696 goto exit;
6697 }
6698
Haynes Mathew George16081042017-05-31 17:16:49 -07006699 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6700 step = "open";
6701 ret = -ENODEV;
6702 goto exit;
6703 }
6704
6705 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6706 if (ret < 0) {
6707 step = "begin";
6708 goto exit;
6709 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006710
Arun Mirpuri5d170872019-03-26 13:21:31 -07006711 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6712 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6713 info->burst_size_frames = in->config.period_size;
6714 ret = platform_get_mmap_data_fd(adev->platform,
6715 in->pcm_device_id, 1 /*capture*/,
6716 &info->shared_memory_fd,
6717 &mmap_size);
6718 if (ret < 0) {
6719 // Fall back to non exclusive mode
6720 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6721 } else {
6722 if (mmap_size < buffer_size) {
6723 step = "mmap";
6724 goto exit;
6725 }
6726 // FIXME: indicate exclusive mode support by returning a negative buffer size
6727 info->buffer_size_frames *= -1;
6728 }
6729
6730 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006731
6732 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6733 if (ret < 0) {
6734 step = "commit";
6735 goto exit;
6736 }
6737
Phil Burke0a86d12019-02-16 22:28:11 -08006738 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
6739
Haynes Mathew George16081042017-05-31 17:16:49 -07006740 in->standby = false;
6741 ret = 0;
6742
6743 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6744 __func__, info->shared_memory_address, info->buffer_size_frames);
6745
6746exit:
6747 if (ret != 0) {
6748 if (in->pcm == NULL) {
6749 ALOGE("%s: %s - %d", __func__, step, ret);
6750 } else {
6751 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6752 pcm_close(in->pcm);
6753 in->pcm = NULL;
6754 }
6755 }
6756 pthread_mutex_unlock(&adev->lock);
6757 return ret;
6758}
6759
6760static int in_get_mmap_position(const struct audio_stream_in *stream,
6761 struct audio_mmap_position *position)
6762{
6763 struct stream_in *in = (struct stream_in *)stream;
6764 ALOGVV("%s", __func__);
6765 if (position == NULL) {
6766 return -EINVAL;
6767 }
6768 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6769 return -ENOSYS;
6770 }
6771 if (in->pcm == NULL) {
6772 return -ENOSYS;
6773 }
6774 struct timespec ts = { 0, 0 };
6775 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6776 if (ret < 0) {
6777 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6778 return ret;
6779 }
Phil Burke0a86d12019-02-16 22:28:11 -08006780 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6781 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006782 return 0;
6783}
6784
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306785static int in_get_active_microphones(const struct audio_stream_in *stream,
6786 struct audio_microphone_characteristic_t *mic_array,
6787 size_t *mic_count) {
6788 struct stream_in *in = (struct stream_in *)stream;
6789 struct audio_device *adev = in->dev;
6790 ALOGVV("%s", __func__);
6791
6792 lock_input_stream(in);
6793 pthread_mutex_lock(&adev->lock);
6794 int ret = platform_get_active_microphones(adev->platform,
6795 audio_channel_count_from_in_mask(in->channel_mask),
6796 in->usecase, mic_array, mic_count);
6797 pthread_mutex_unlock(&adev->lock);
6798 pthread_mutex_unlock(&in->lock);
6799
6800 return ret;
6801}
6802
6803static int adev_get_microphones(const struct audio_hw_device *dev,
6804 struct audio_microphone_characteristic_t *mic_array,
6805 size_t *mic_count) {
6806 struct audio_device *adev = (struct audio_device *)dev;
6807 ALOGVV("%s", __func__);
6808
6809 pthread_mutex_lock(&adev->lock);
6810 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6811 pthread_mutex_unlock(&adev->lock);
6812
6813 return ret;
6814}
juyuchendb308c22019-01-21 11:57:17 -07006815
6816static void in_update_sink_metadata(struct audio_stream_in *stream,
6817 const struct sink_metadata *sink_metadata) {
6818
6819 if (stream == NULL
6820 || sink_metadata == NULL
6821 || sink_metadata->tracks == NULL) {
6822 return;
6823 }
6824
6825 int error = 0;
6826 struct stream_in *in = (struct stream_in *)stream;
6827 struct audio_device *adev = in->dev;
6828 audio_devices_t device = AUDIO_DEVICE_NONE;
6829
6830 if (sink_metadata->track_count != 0)
6831 device = sink_metadata->tracks->dest_device;
6832
6833 lock_input_stream(in);
6834 pthread_mutex_lock(&adev->lock);
6835 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
6836
6837 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
6838 && device != AUDIO_DEVICE_NONE
6839 && adev->voice_tx_output != NULL) {
6840 /* Use the rx device from afe-proxy record to route voice call because
6841 there is no routing if tx device is on primary hal and rx device
6842 is on other hal during voice call. */
6843 adev->voice_tx_output->devices = device;
6844
6845 if (!voice_is_call_state_active(adev)) {
6846 if (adev->mode == AUDIO_MODE_IN_CALL) {
6847 adev->current_call_output = adev->voice_tx_output;
6848 error = voice_start_call(adev);
6849 if (error != 0)
6850 ALOGE("%s: start voice call failed %d", __func__, error);
6851 }
6852 } else {
6853 adev->current_call_output = adev->voice_tx_output;
6854 voice_update_devices_for_all_voice_usecases(adev);
6855 }
6856 }
6857
6858 pthread_mutex_unlock(&adev->lock);
6859 pthread_mutex_unlock(&in->lock);
6860}
6861
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306862int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006863 audio_io_handle_t handle,
6864 audio_devices_t devices,
6865 audio_output_flags_t flags,
6866 struct audio_config *config,
6867 struct audio_stream_out **stream_out,
6868 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006869{
6870 struct audio_device *adev = (struct audio_device *)dev;
6871 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05306872 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006873 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006874 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306875 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006876 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6877 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6878 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6879 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006880 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07006881 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
6882 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006883 bool force_haptic_path =
6884 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07006885 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006886
kunleizdff872d2018-08-20 14:40:33 +08006887 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006888 is_usb_dev = false;
6889 devices = AUDIO_DEVICE_OUT_SPEAKER;
6890 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6891 __func__, devices);
6892 }
6893
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006894 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306895
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006896 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6897
Mingming Yin3a941d42016-02-17 18:08:05 -08006898 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6899 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306900 devices, flags, &out->stream);
6901
6902
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006903 if (!out) {
6904 return -ENOMEM;
6905 }
6906
Haynes Mathew George204045b2015-02-25 20:32:03 -08006907 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006908 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306909 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006910 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006911 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6912
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006913 if (devices == AUDIO_DEVICE_NONE)
6914 devices = AUDIO_DEVICE_OUT_SPEAKER;
6915
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006916 out->flags = flags;
6917 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006918 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006919 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006920 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306921 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306922 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6923 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6924 else
6925 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006926 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006927 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006928 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306929 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306930 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306931 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006932 out->hal_output_suspend_supported = 0;
6933 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306934 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306935 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306936 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006937
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306938 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306939 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006940 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6941
Aalique Grahame22e49102018-12-18 14:23:57 -08006942 if (direct_dev &&
6943 (audio_is_linear_pcm(out->format) ||
6944 config->format == AUDIO_FORMAT_DEFAULT) &&
6945 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6946 audio_format_t req_format = config->format;
6947 audio_channel_mask_t req_channel_mask = config->channel_mask;
6948 uint32_t req_sample_rate = config->sample_rate;
6949
6950 pthread_mutex_lock(&adev->lock);
6951 if (is_hdmi) {
6952 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6953 ret = read_hdmi_sink_caps(out);
6954 if (config->sample_rate == 0)
6955 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6956 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6957 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6958 if (config->format == AUDIO_FORMAT_DEFAULT)
6959 config->format = AUDIO_FORMAT_PCM_16_BIT;
6960 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006961 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6962 &config->format,
6963 &out->supported_formats[0],
6964 MAX_SUPPORTED_FORMATS,
6965 &config->channel_mask,
6966 &out->supported_channel_masks[0],
6967 MAX_SUPPORTED_CHANNEL_MASKS,
6968 &config->sample_rate,
6969 &out->supported_sample_rates[0],
6970 MAX_SUPPORTED_SAMPLE_RATES);
6971 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006972 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006973
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006974 pthread_mutex_unlock(&adev->lock);
6975 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006976 if (ret == -ENOSYS) {
6977 /* ignore and go with default */
6978 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006979 }
6980 // For MMAP NO IRQ, allow conversions in ADSP
6981 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6982 goto error_open;
6983 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006984 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006985 goto error_open;
6986 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006987
6988 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6989 config->sample_rate = req_sample_rate;
6990 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6991 config->channel_mask = req_channel_mask;
6992 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6993 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006994 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006995
6996 out->sample_rate = config->sample_rate;
6997 out->channel_mask = config->channel_mask;
6998 out->format = config->format;
6999 if (is_hdmi) {
7000 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7001 out->config = pcm_config_hdmi_multi;
7002 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7003 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7004 out->config = pcm_config_mmap_playback;
7005 out->stream.start = out_start;
7006 out->stream.stop = out_stop;
7007 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7008 out->stream.get_mmap_position = out_get_mmap_position;
7009 } else {
7010 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7011 out->config = pcm_config_hifi;
7012 }
7013
7014 out->config.rate = out->sample_rate;
7015 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7016 if (is_hdmi) {
7017 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7018 audio_bytes_per_sample(out->format));
7019 }
7020 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08007021 }
7022
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007023 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07007024 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007025 if (!voice_extn_is_compress_voip_supported()) {
7026 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7027 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007028 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7029 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007030 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7031 out->format = AUDIO_FORMAT_PCM_16_BIT;
Aniket Kumar Lata8426d1f2019-06-10 15:25:53 -07007032 out->volume_l = INVALID_OUT_VOLUME;
7033 out->volume_r = INVALID_OUT_VOLUME;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007034
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007035 out->config = default_pcm_config_voip_copp;
7036 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7037 out->config.rate = out->sample_rate;
7038 }
7039 } else {
7040 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7041 voice_extn_compress_voip_is_active(out->dev)) &&
7042 (voice_extn_compress_voip_is_config_supported(config))) {
7043 ret = voice_extn_compress_voip_open_output_stream(out);
7044 if (ret != 0) {
7045 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7046 __func__, ret);
7047 goto error_open;
7048 }
7049 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007050 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007051 } else if (audio_is_linear_pcm(out->format) &&
7052 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7053 out->channel_mask = config->channel_mask;
7054 out->sample_rate = config->sample_rate;
7055 out->format = config->format;
7056 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7057 // does this change?
7058 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7059 out->config.rate = config->sample_rate;
7060 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7061 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7062 audio_bytes_per_sample(config->format));
7063 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007064 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307065 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307066 pthread_mutex_lock(&adev->lock);
7067 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7068 pthread_mutex_unlock(&adev->lock);
7069
7070 // reject offload during card offline to allow
7071 // fallback to s/w paths
7072 if (offline) {
7073 ret = -ENODEV;
7074 goto error_open;
7075 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007076
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007077 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7078 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7079 ALOGE("%s: Unsupported Offload information", __func__);
7080 ret = -EINVAL;
7081 goto error_open;
7082 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007083
Atul Khare3fa6e542017-08-09 00:56:17 +05307084 if (config->offload_info.format == 0)
7085 config->offload_info.format = config->format;
7086 if (config->offload_info.sample_rate == 0)
7087 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007088
Mingming Yin90310102013-11-13 16:57:00 -08007089 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307090 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007091 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007092 ret = -EINVAL;
7093 goto error_open;
7094 }
7095
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007096 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7097 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7098 (audio_extn_passthru_is_passthrough_stream(out)) &&
7099 !((config->sample_rate == 48000) ||
7100 (config->sample_rate == 96000) ||
7101 (config->sample_rate == 192000))) {
7102 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7103 __func__, config->sample_rate, config->offload_info.format);
7104 ret = -EINVAL;
7105 goto error_open;
7106 }
7107
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007108 out->compr_config.codec = (struct snd_codec *)
7109 calloc(1, sizeof(struct snd_codec));
7110
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007111 if (!out->compr_config.codec) {
7112 ret = -ENOMEM;
7113 goto error_open;
7114 }
7115
Dhananjay Kumarac341582017-02-23 23:42:25 +05307116 out->stream.pause = out_pause;
7117 out->stream.resume = out_resume;
7118 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307119 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307120 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007121 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307122 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007123 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307124 } else {
7125 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7126 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007127 }
vivek mehta446c3962015-09-14 10:57:35 -07007128
7129 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007130 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7131 config->format == 0 && config->sample_rate == 0 &&
7132 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007133 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007134 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7135 } else {
7136 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7137 ret = -EEXIST;
7138 goto error_open;
7139 }
vivek mehta446c3962015-09-14 10:57:35 -07007140 }
7141
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007142 if (config->offload_info.channel_mask)
7143 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007144 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007145 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007146 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007147 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307148 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007149 ret = -EINVAL;
7150 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007151 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007152
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007153 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007154 out->sample_rate = config->offload_info.sample_rate;
7155
Mingming Yin3ee55c62014-08-04 14:23:35 -07007156 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007157
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307158 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307159 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307160 audio_extn_dolby_send_ddp_endp_params(adev);
7161 audio_extn_dolby_set_dmid(adev);
7162 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007163
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007164 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007165 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007166 out->compr_config.codec->bit_rate =
7167 config->offload_info.bit_rate;
7168 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307169 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007170 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307171 /* Update bit width only for non passthrough usecases.
7172 * For passthrough usecases, the output will always be opened @16 bit
7173 */
7174 if (!audio_extn_passthru_is_passthrough_stream(out))
7175 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307176
7177 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7178 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7179 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7180
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007181 /*TODO: Do we need to change it for passthrough */
7182 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007183
Manish Dewangana6fc5442015-08-24 20:30:31 +05307184 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7185 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307186 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307187 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307188 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7189 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307190
7191 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7192 AUDIO_FORMAT_PCM) {
7193
7194 /*Based on platform support, configure appropriate alsa format for corresponding
7195 *hal input format.
7196 */
7197 out->compr_config.codec->format = hal_format_to_alsa(
7198 config->offload_info.format);
7199
Ashish Jain83a6cc22016-06-28 14:34:17 +05307200 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307201 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307202 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307203
Dhananjay Kumarac341582017-02-23 23:42:25 +05307204 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307205 *hal input format and alsa format might differ based on platform support.
7206 */
7207 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307208 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307209
7210 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7211
7212 /* Check if alsa session is configured with the same format as HAL input format,
7213 * if not then derive correct fragment size needed to accomodate the
7214 * conversion of HAL input format to alsa format.
7215 */
7216 audio_extn_utils_update_direct_pcm_fragment_size(out);
7217
7218 /*if hal input and output fragment size is different this indicates HAL input format is
7219 *not same as the alsa format
7220 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307221 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307222 /*Allocate a buffer to convert input data to the alsa configured format.
7223 *size of convert buffer is equal to the size required to hold one fragment size
7224 *worth of pcm data, this is because flinger does not write more than fragment_size
7225 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307226 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7227 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307228 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7229 ret = -ENOMEM;
7230 goto error_open;
7231 }
7232 }
7233 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7234 out->compr_config.fragment_size =
7235 audio_extn_passthru_get_buffer_size(&config->offload_info);
7236 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7237 } else {
7238 out->compr_config.fragment_size =
7239 platform_get_compress_offload_buffer_size(&config->offload_info);
7240 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7241 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007242
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307243 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7244 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7245 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007246 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307247 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007248
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307249 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7250 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7251 }
7252
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007253 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7254 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007255
Manish Dewangan69426c82017-01-30 17:35:36 +05307256 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7257 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7258 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7259 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7260 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7261 } else {
7262 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7263 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007264
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307265 memset(&out->channel_map_param, 0,
7266 sizeof(struct audio_out_channel_map_param));
7267
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007268 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307269 out->send_next_track_params = false;
7270 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007271 out->offload_state = OFFLOAD_STATE_IDLE;
7272 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007273 out->writeAt.tv_sec = 0;
7274 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007275
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007276 audio_extn_dts_create_state_notifier_node(out->usecase);
7277
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007278 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7279 __func__, config->offload_info.version,
7280 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307281
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307282 /* Check if DSD audio format is supported in codec
7283 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307284 */
7285
7286 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307287 (!platform_check_codec_dsd_support(adev->platform) ||
7288 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307289 ret = -EINVAL;
7290 goto error_open;
7291 }
7292
Ashish Jain5106d362016-05-11 19:23:33 +05307293 /* Disable gapless if any of the following is true
7294 * passthrough playback
7295 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307296 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307297 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307298 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307299 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007300 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307301 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307302 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307303 check_and_set_gapless_mode(adev, false);
7304 } else
7305 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007306
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307307 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007308 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7309 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307310 if (config->format == AUDIO_FORMAT_DSD) {
7311 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7312 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7313 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007314
7315 create_offload_callback_thread(out);
7316
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007317 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007318 switch (config->sample_rate) {
7319 case 0:
7320 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7321 break;
7322 case 8000:
7323 case 16000:
7324 case 48000:
7325 out->sample_rate = config->sample_rate;
7326 break;
7327 default:
7328 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7329 config->sample_rate);
7330 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7331 ret = -EINVAL;
7332 goto error_open;
7333 }
7334 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7335 switch (config->channel_mask) {
7336 case AUDIO_CHANNEL_NONE:
7337 case AUDIO_CHANNEL_OUT_STEREO:
7338 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7339 break;
7340 default:
7341 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7342 config->channel_mask);
7343 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7344 ret = -EINVAL;
7345 goto error_open;
7346 }
7347 switch (config->format) {
7348 case AUDIO_FORMAT_DEFAULT:
7349 case AUDIO_FORMAT_PCM_16_BIT:
7350 out->format = AUDIO_FORMAT_PCM_16_BIT;
7351 break;
7352 default:
7353 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7354 config->format);
7355 config->format = AUDIO_FORMAT_PCM_16_BIT;
7356 ret = -EINVAL;
7357 goto error_open;
7358 }
7359
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307360 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007361 if (ret != 0) {
7362 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007363 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007364 goto error_open;
7365 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007366 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007367 switch (config->sample_rate) {
7368 case 0:
7369 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7370 break;
7371 case 8000:
7372 case 16000:
7373 case 48000:
7374 out->sample_rate = config->sample_rate;
7375 break;
7376 default:
7377 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7378 config->sample_rate);
7379 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7380 ret = -EINVAL;
7381 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007382 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007383 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7384 switch (config->channel_mask) {
7385 case AUDIO_CHANNEL_NONE:
7386 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7387 break;
7388 case AUDIO_CHANNEL_OUT_STEREO:
7389 out->channel_mask = config->channel_mask;
7390 break;
7391 default:
7392 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7393 config->channel_mask);
7394 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7395 ret = -EINVAL;
7396 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007397 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007398 switch (config->format) {
7399 case AUDIO_FORMAT_DEFAULT:
7400 out->format = AUDIO_FORMAT_PCM_16_BIT;
7401 break;
7402 case AUDIO_FORMAT_PCM_16_BIT:
7403 out->format = config->format;
7404 break;
7405 default:
7406 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7407 config->format);
7408 config->format = AUDIO_FORMAT_PCM_16_BIT;
7409 ret = -EINVAL;
7410 break;
7411 }
7412 if (ret != 0)
7413 goto error_open;
7414
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007415 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7416 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007417 out->config.rate = out->sample_rate;
7418 out->config.channels =
7419 audio_channel_count_from_out_mask(out->channel_mask);
7420 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007421 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007422 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307423 unsigned int channels = 0;
7424 /*Update config params to default if not set by the caller*/
7425 if (config->sample_rate == 0)
7426 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7427 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7428 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7429 if (config->format == AUDIO_FORMAT_DEFAULT)
7430 config->format = AUDIO_FORMAT_PCM_16_BIT;
7431
7432 channels = audio_channel_count_from_out_mask(out->channel_mask);
7433
Varun Balaraje49253e2017-07-06 19:48:56 +05307434 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7435 out->usecase = get_interactive_usecase(adev);
7436 out->config = pcm_config_low_latency;
7437 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307438 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007439 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7440 out->flags);
7441 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007442 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7443 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7444 out->config = pcm_config_mmap_playback;
7445 out->stream.start = out_start;
7446 out->stream.stop = out_stop;
7447 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7448 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307449 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7450 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007451 out->hal_output_suspend_supported =
7452 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7453 out->dynamic_pm_qos_config_supported =
7454 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7455 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007456 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7457 } else {
7458 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7459 //the mixer path will be a string similar to "low-latency-playback resume"
7460 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7461 strlcat(out->pm_qos_mixer_path,
7462 " resume", MAX_MIXER_PATH_LEN);
7463 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7464 out->pm_qos_mixer_path);
7465 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307466 out->config = pcm_config_low_latency;
7467 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7468 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7469 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307470 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7471 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7472 if (out->config.period_size <= 0) {
7473 ALOGE("Invalid configuration period size is not valid");
7474 ret = -EINVAL;
7475 goto error_open;
7476 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007477 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7478 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7479 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007480 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7481 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7482 out->config = pcm_config_haptics_audio;
7483 if (force_haptic_path)
7484 adev->haptics_config = pcm_config_haptics_audio;
7485 else
7486 adev->haptics_config = pcm_config_haptics;
7487
7488 out->config.channels =
7489 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7490
7491 if (force_haptic_path) {
7492 out->config.channels = 1;
7493 adev->haptics_config.channels = 1;
7494 } else
7495 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307496 } else {
7497 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007498 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7499 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307500 }
7501 out->hal_ip_format = format = out->format;
7502 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7503 out->hal_op_format = pcm_format_to_hal(out->config.format);
7504 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7505 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007506 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307507 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307508 if (out->hal_ip_format != out->hal_op_format) {
7509 uint32_t buffer_size = out->config.period_size *
7510 format_to_bitwidth_table[out->hal_op_format] *
7511 out->config.channels;
7512 out->convert_buffer = calloc(1, buffer_size);
7513 if (out->convert_buffer == NULL){
7514 ALOGE("Allocation failed for convert buffer for size %d",
7515 out->compr_config.fragment_size);
7516 ret = -ENOMEM;
7517 goto error_open;
7518 }
7519 ALOGD("Convert buffer allocated of size %d", buffer_size);
7520 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007521 }
7522
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007523 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7524 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307525
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007526 /* TODO remove this hardcoding and check why width is zero*/
7527 if (out->bit_width == 0)
7528 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307529 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007530 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007531 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307532 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307533 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007534 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007535 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7536 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007537 if(adev->primary_output == NULL)
7538 adev->primary_output = out;
7539 else {
7540 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007541 ret = -EEXIST;
7542 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007543 }
7544 }
7545
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007546 /* Check if this usecase is already existing */
7547 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007548 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7549 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007550 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007551 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007552 ret = -EEXIST;
7553 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007554 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007555
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007556 pthread_mutex_unlock(&adev->lock);
7557
7558 out->stream.common.get_sample_rate = out_get_sample_rate;
7559 out->stream.common.set_sample_rate = out_set_sample_rate;
7560 out->stream.common.get_buffer_size = out_get_buffer_size;
7561 out->stream.common.get_channels = out_get_channels;
7562 out->stream.common.get_format = out_get_format;
7563 out->stream.common.set_format = out_set_format;
7564 out->stream.common.standby = out_standby;
7565 out->stream.common.dump = out_dump;
7566 out->stream.common.set_parameters = out_set_parameters;
7567 out->stream.common.get_parameters = out_get_parameters;
7568 out->stream.common.add_audio_effect = out_add_audio_effect;
7569 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7570 out->stream.get_latency = out_get_latency;
7571 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007572#ifdef NO_AUDIO_OUT
7573 out->stream.write = out_write_for_no_output;
7574#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007575 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007576#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007577 out->stream.get_render_position = out_get_render_position;
7578 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007579 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007580
Haynes Mathew George16081042017-05-31 17:16:49 -07007581 if (out->realtime)
7582 out->af_period_multiplier = af_period_multiplier;
7583 else
7584 out->af_period_multiplier = 1;
7585
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007586 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007587 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007588 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007589
7590 config->format = out->stream.common.get_format(&out->stream.common);
7591 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7592 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307593 register_format(out->format, out->supported_formats);
7594 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7595 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007596
Aalique Grahame22e49102018-12-18 14:23:57 -08007597 out->error_log = error_log_create(
7598 ERROR_LOG_ENTRIES,
7599 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7600
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307601 /*
7602 By locking output stream before registering, we allow the callback
7603 to update stream's state only after stream's initial state is set to
7604 adev state.
7605 */
7606 lock_output_stream(out);
7607 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7608 pthread_mutex_lock(&adev->lock);
7609 out->card_status = adev->card_status;
7610 pthread_mutex_unlock(&adev->lock);
7611 pthread_mutex_unlock(&out->lock);
7612
Aalique Grahame22e49102018-12-18 14:23:57 -08007613 stream_app_type_cfg_init(&out->app_type_cfg);
7614
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007615 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307616 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007617 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007618
7619 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7620 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7621 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007622 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307623 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007624 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007625 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307626 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
7627 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007628 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7629 out->usecase, PCM_PLAYBACK);
7630 hdlr_stream_cfg.flags = out->flags;
7631 hdlr_stream_cfg.type = PCM_PLAYBACK;
7632 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7633 &hdlr_stream_cfg);
7634 if (ret) {
7635 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7636 out->adsp_hdlr_stream_handle = NULL;
7637 }
7638 }
Gangadhar Sb0210342019-02-22 17:39:41 +05307639 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
7640 is_direct_passthough, false);
7641 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
7642 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007643 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007644 if (ret < 0) {
7645 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7646 out->ip_hdlr_handle = NULL;
7647 }
7648 }
Derek Chenf939fb72018-11-13 13:34:41 -08007649
7650 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7651 calloc(1, sizeof(streams_output_ctxt_t));
7652 if (out_ctxt == NULL) {
7653 ALOGE("%s fail to allocate output ctxt", __func__);
7654 ret = -ENOMEM;
7655 goto error_open;
7656 }
7657 out_ctxt->output = out;
7658
7659 pthread_mutex_lock(&adev->lock);
7660 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7661 pthread_mutex_unlock(&adev->lock);
7662
Eric Laurent994a6932013-07-17 11:51:42 -07007663 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007664 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007665
7666error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307667 if (out->convert_buffer)
7668 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007669 free(out);
7670 *stream_out = NULL;
7671 ALOGD("%s: exit: ret %d", __func__, ret);
7672 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007673}
7674
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307675void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007676 struct audio_stream_out *stream)
7677{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007678 struct stream_out *out = (struct stream_out *)stream;
7679 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007680 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007681
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007682 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307683
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307684 // must deregister from sndmonitor first to prevent races
7685 // between the callback and close_stream
7686 audio_extn_snd_mon_unregister_listener(out);
7687
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007688 /* close adsp hdrl session before standby */
7689 if (out->adsp_hdlr_stream_handle) {
7690 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7691 if (ret)
7692 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7693 out->adsp_hdlr_stream_handle = NULL;
7694 }
7695
Manish Dewangan21a850a2017-08-14 12:03:55 +05307696 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007697 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7698 out->ip_hdlr_handle = NULL;
7699 }
7700
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007701 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307702 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007703 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307704 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307705 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007706 if(ret != 0)
7707 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7708 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007709 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007710 out_standby(&stream->common);
7711
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007712 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007713 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007714 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007715 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007716 if (out->compr_config.codec != NULL)
7717 free(out->compr_config.codec);
7718 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007719
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307720 out->a2dp_compress_mute = false;
7721
Varun Balaraje49253e2017-07-06 19:48:56 +05307722 if (is_interactive_usecase(out->usecase))
7723 free_interactive_usecase(adev, out->usecase);
7724
Ashish Jain83a6cc22016-06-28 14:34:17 +05307725 if (out->convert_buffer != NULL) {
7726 free(out->convert_buffer);
7727 out->convert_buffer = NULL;
7728 }
7729
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007730 if (adev->voice_tx_output == out)
7731 adev->voice_tx_output = NULL;
7732
Aalique Grahame22e49102018-12-18 14:23:57 -08007733 error_log_destroy(out->error_log);
7734 out->error_log = NULL;
7735
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307736 if (adev->primary_output == out)
7737 adev->primary_output = NULL;
7738
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007739 pthread_cond_destroy(&out->cond);
7740 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007741
7742 pthread_mutex_lock(&adev->lock);
7743 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7744 if (out_ctxt != NULL) {
7745 list_remove(&out_ctxt->list);
7746 free(out_ctxt);
7747 } else {
7748 ALOGW("%s, output stream already closed", __func__);
7749 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007750 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007751 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007752 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007753}
7754
7755static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7756{
7757 struct audio_device *adev = (struct audio_device *)dev;
7758 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007759 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007760 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007761 int ret;
7762 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007763 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08007764 struct listnode *node;
7765 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007766
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007767 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007768 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007769
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307770 if (!parms)
7771 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307772
Zhou Songd6d71752019-05-21 18:08:51 +08007773 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307774 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7775 if (ret >= 0) {
7776 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08007777 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307778 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08007779 } else {
7780 ALOGD("sco is off, reset sco and route device to handset/mic");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307781 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08007782 audio_extn_sco_reset_configuration();
7783 list_for_each(node, &adev->usecase_list) {
7784 usecase = node_to_item(node, struct audio_usecase, list);
7785 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
7786 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
7787 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
7788 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
7789 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
7790 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
7791 else
7792 continue;
7793 select_devices(adev, usecase->id);
7794 }
7795 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307796 }
7797
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007798 status = voice_set_parameters(adev, parms);
7799 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007800 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007801
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007802 status = platform_set_parameters(adev->platform, parms);
7803 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007804 goto done;
7805
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007806 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7807 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007808 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007809 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7810 adev->bluetooth_nrec = true;
7811 else
7812 adev->bluetooth_nrec = false;
7813 }
7814
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007815 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7816 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007817 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7818 adev->screen_off = false;
7819 else
7820 adev->screen_off = true;
7821 }
7822
Eric Laurent4b084132018-10-19 17:33:43 -07007823 ret = str_parms_get_int(parms, "rotation", &val);
7824 if (ret >= 0) {
7825 bool reverse_speakers = false;
7826 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
7827 switch (val) {
7828 // FIXME: note that the code below assumes that the speakers are in the correct placement
7829 // relative to the user when the device is rotated 90deg from its default rotation. This
7830 // assumption is device-specific, not platform-specific like this code.
7831 case 270:
7832 reverse_speakers = true;
7833 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
7834 break;
7835 case 0:
7836 case 180:
7837 camera_rotation = CAMERA_ROTATION_PORTRAIT;
7838 break;
7839 case 90:
7840 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
7841 break;
7842 default:
7843 ALOGE("%s: unexpected rotation of %d", __func__, val);
7844 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007845 }
Eric Laurent4b084132018-10-19 17:33:43 -07007846 if (status == 0) {
7847 // check and set swap
7848 // - check if orientation changed and speaker active
7849 // - set rotation and cache the rotation value
7850 adev->camera_orientation =
7851 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
7852 if (!audio_extn_is_maxx_audio_enabled())
7853 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
7854 }
7855 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007856
Mingming Yin514a8bc2014-07-29 15:22:21 -07007857 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7858 if (ret >= 0) {
7859 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7860 adev->bt_wb_speech_enabled = true;
7861 else
7862 adev->bt_wb_speech_enabled = false;
7863 }
7864
Zhou Song12c29502019-03-16 10:37:18 +08007865 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
7866 if (ret >= 0) {
7867 val = atoi(value);
7868 adev->swb_speech_mode = val;
7869 }
7870
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007871 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7872 if (ret >= 0) {
7873 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307874 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007875 if (audio_is_output_device(val) &&
7876 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007877 ALOGV("cache new ext disp type and edid");
7878 ret = platform_get_ext_disp_type(adev->platform);
7879 if (ret < 0) {
7880 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307881 } else {
7882 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007883 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307884 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007885 /*
7886 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7887 * Per AudioPolicyManager, USB device is higher priority than WFD.
7888 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7889 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7890 * starting voice call on USB
7891 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007892 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307893 if (ret >= 0)
7894 audio_extn_usb_add_device(device, atoi(value));
7895
Zhou Song6f862822017-11-06 17:27:57 +08007896 if (!audio_extn_usb_is_tunnel_supported()) {
7897 ALOGV("detected USB connect .. disable proxy");
7898 adev->allow_afe_proxy_usage = false;
7899 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007900 }
7901 }
7902
7903 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7904 if (ret >= 0) {
7905 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307906 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007907 /*
7908 * The HDMI / Displayport disconnect handling has been moved to
7909 * audio extension to ensure that its parameters are not
7910 * invalidated prior to updating sysfs of the disconnect event
7911 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7912 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307913 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007914 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307915 if (ret >= 0)
7916 audio_extn_usb_remove_device(device, atoi(value));
7917
Zhou Song6f862822017-11-06 17:27:57 +08007918 if (!audio_extn_usb_is_tunnel_supported()) {
7919 ALOGV("detected USB disconnect .. enable proxy");
7920 adev->allow_afe_proxy_usage = true;
7921 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007922 }
7923 }
7924
Aalique Grahame22e49102018-12-18 14:23:57 -08007925 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007926 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007927
7928 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007929 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307930 struct audio_usecase *usecase;
7931 struct listnode *node;
7932 list_for_each(node, &adev->usecase_list) {
7933 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05307934 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007935 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307936 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007937
7938 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307939 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007940 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307941 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307942 //force device switch to re configure encoder
7943 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307944 audio_extn_a2dp_set_handoff_mode(false);
7945 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307946 break;
7947 }
7948 }
7949 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007950
7951 //handle vr audio setparam
7952 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7953 value, sizeof(value));
7954 if (ret >= 0) {
7955 ALOGI("Setting vr mode to be %s", value);
7956 if (!strncmp(value, "true", 4)) {
7957 adev->vr_audio_mode_enabled = true;
7958 ALOGI("Setting vr mode to true");
7959 } else if (!strncmp(value, "false", 5)) {
7960 adev->vr_audio_mode_enabled = false;
7961 ALOGI("Setting vr mode to false");
7962 } else {
7963 ALOGI("wrong vr mode set");
7964 }
7965 }
7966
Eric Laurent4b084132018-10-19 17:33:43 -07007967 //FIXME: to be replaced by proper video capture properties API
7968 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
7969 if (ret >= 0) {
7970 int camera_facing = CAMERA_FACING_BACK;
7971 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
7972 camera_facing = CAMERA_FACING_FRONT;
7973 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
7974 camera_facing = CAMERA_FACING_BACK;
7975 else {
7976 ALOGW("%s: invalid camera facing value: %s", __func__, value);
7977 goto done;
7978 }
7979 adev->camera_orientation =
7980 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
7981 struct audio_usecase *usecase;
7982 struct listnode *node;
7983 list_for_each(node, &adev->usecase_list) {
7984 usecase = node_to_item(node, struct audio_usecase, list);
7985 struct stream_in *in = usecase->stream.in;
7986 if (usecase->type == PCM_CAPTURE && in != NULL &&
7987 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
7988 select_devices(adev, in->usecase);
7989 }
7990 }
7991 }
7992
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307993 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007994done:
7995 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007996 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307997error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007998 ALOGV("%s: exit with code(%d)", __func__, status);
7999 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008000}
8001
8002static char* adev_get_parameters(const struct audio_hw_device *dev,
8003 const char *keys)
8004{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308005 ALOGD("%s:%s", __func__, keys);
8006
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008007 struct audio_device *adev = (struct audio_device *)dev;
8008 struct str_parms *reply = str_parms_create();
8009 struct str_parms *query = str_parms_create_str(keys);
8010 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05308011 char value[256] = {0};
8012 int ret = 0;
8013
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008014 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08008015 if (reply) {
8016 str_parms_destroy(reply);
8017 }
8018 if (query) {
8019 str_parms_destroy(query);
8020 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008021 ALOGE("adev_get_parameters: failed to create query or reply");
8022 return NULL;
8023 }
8024
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008025 //handle vr audio getparam
8026
8027 ret = str_parms_get_str(query,
8028 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8029 value, sizeof(value));
8030
8031 if (ret >= 0) {
8032 bool vr_audio_enabled = false;
8033 pthread_mutex_lock(&adev->lock);
8034 vr_audio_enabled = adev->vr_audio_mode_enabled;
8035 pthread_mutex_unlock(&adev->lock);
8036
8037 ALOGI("getting vr mode to %d", vr_audio_enabled);
8038
8039 if (vr_audio_enabled) {
8040 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8041 "true");
8042 goto exit;
8043 } else {
8044 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8045 "false");
8046 goto exit;
8047 }
8048 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008049
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008050 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008051 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008052 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008053 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008054 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308055 pthread_mutex_unlock(&adev->lock);
8056
Naresh Tannirud7205b62014-06-20 02:54:48 +05308057exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008058 str = str_parms_to_str(reply);
8059 str_parms_destroy(query);
8060 str_parms_destroy(reply);
8061
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308062 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008063 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008064}
8065
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008066static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008067{
8068 return 0;
8069}
8070
8071static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8072{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008073 int ret;
8074 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008075
8076 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8077
Haynes Mathew George5191a852013-09-11 14:19:36 -07008078 pthread_mutex_lock(&adev->lock);
8079 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008080 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008081 pthread_mutex_unlock(&adev->lock);
8082 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008083}
8084
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008085static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8086 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008087{
8088 return -ENOSYS;
8089}
8090
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008091static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8092 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008093{
8094 return -ENOSYS;
8095}
8096
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008097static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8098 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008099{
8100 return -ENOSYS;
8101}
8102
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008103static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8104 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008105{
8106 return -ENOSYS;
8107}
8108
8109static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8110{
8111 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008112 struct listnode *node;
8113 struct audio_usecase *usecase = NULL;
8114 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008115
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008116 pthread_mutex_lock(&adev->lock);
8117 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008118 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008119 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008120 if (voice_is_in_call(adev) &&
8121 (mode == AUDIO_MODE_NORMAL ||
8122 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008123 list_for_each(node, &adev->usecase_list) {
8124 usecase = node_to_item(node, struct audio_usecase, list);
8125 if (usecase->type == VOICE_CALL)
8126 break;
8127 }
8128 if (usecase &&
8129 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8130 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8131 true);
8132 if (ret != 0) {
8133 /* default service interval was successfully updated,
8134 reopen USB backend with new service interval */
8135 check_usecases_codec_backend(adev,
8136 usecase,
8137 usecase->out_snd_device);
8138 }
8139 }
8140
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008141 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008142 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008143 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008144 // restore device for other active usecases after stop call
8145 list_for_each(node, &adev->usecase_list) {
8146 usecase = node_to_item(node, struct audio_usecase, list);
8147 select_devices(adev, usecase->id);
8148 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008149 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008150 }
8151 pthread_mutex_unlock(&adev->lock);
8152 return 0;
8153}
8154
8155static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8156{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008157 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008158 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008159
8160 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008161 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008162 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008163
Derek Chend2530072014-11-24 12:39:14 -08008164 if (adev->ext_hw_plugin)
8165 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008166
8167 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008168 pthread_mutex_unlock(&adev->lock);
8169
8170 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008171}
8172
8173static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8174{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008175 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008176 return 0;
8177}
8178
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008179static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008180 const struct audio_config *config)
8181{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008182 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008183
Aalique Grahame22e49102018-12-18 14:23:57 -08008184 /* Don't know if USB HIFI in this context so use true to be conservative */
8185 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8186 true /*is_usb_hifi */) != 0)
8187 return 0;
8188
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008189 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8190 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008191}
8192
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008193static bool adev_input_allow_hifi_record(struct audio_device *adev,
8194 audio_devices_t devices,
8195 audio_input_flags_t flags,
8196 audio_source_t source) {
8197 const bool allowed = true;
8198
8199 if (!audio_is_usb_in_device(devices))
8200 return !allowed;
8201
8202 switch (flags) {
8203 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008204 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008205 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8206 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008207 default:
8208 return !allowed;
8209 }
8210
8211 switch (source) {
8212 case AUDIO_SOURCE_DEFAULT:
8213 case AUDIO_SOURCE_MIC:
8214 case AUDIO_SOURCE_UNPROCESSED:
8215 break;
8216 default:
8217 return !allowed;
8218 }
8219
8220 switch (adev->mode) {
8221 case 0:
8222 break;
8223 default:
8224 return !allowed;
8225 }
8226
8227 return allowed;
8228}
8229
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008230static int adev_update_voice_comm_input_stream(struct stream_in *in,
8231 struct audio_config *config)
8232{
8233 bool valid_rate = (config->sample_rate == 8000 ||
8234 config->sample_rate == 16000 ||
8235 config->sample_rate == 32000 ||
8236 config->sample_rate == 48000);
8237 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8238
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008239 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008240 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008241 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8242 in->config = default_pcm_config_voip_copp;
8243 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8244 DEFAULT_VOIP_BUF_DURATION_MS,
8245 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008246 } else {
8247 ALOGW("%s No valid input in voip, use defaults"
8248 "sample rate %u, channel mask 0x%X",
8249 __func__, config->sample_rate, in->channel_mask);
8250 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008251 in->config.rate = config->sample_rate;
8252 in->sample_rate = config->sample_rate;
8253 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008254 //XXX needed for voice_extn_compress_voip_open_input_stream
8255 in->config.rate = config->sample_rate;
8256 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8257 voice_extn_compress_voip_is_active(in->dev)) &&
8258 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8259 valid_rate && valid_ch) {
8260 voice_extn_compress_voip_open_input_stream(in);
8261 // update rate entries to match config from AF
8262 in->config.rate = config->sample_rate;
8263 in->sample_rate = config->sample_rate;
8264 } else {
8265 ALOGW("%s compress voip not active, use defaults", __func__);
8266 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008267 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008268 return 0;
8269}
8270
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008271static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008272 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008273 audio_devices_t devices,
8274 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008275 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308276 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008277 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008278 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008279{
8280 struct audio_device *adev = (struct audio_device *)dev;
8281 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008282 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008283 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008284 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308285 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008286 bool is_usb_dev = audio_is_usb_in_device(devices);
8287 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8288 devices,
8289 flags,
8290 source);
Andy Hung94320602018-10-29 18:31:12 -07008291 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8292 " sample_rate %u, channel_mask %#x, format %#x",
8293 __func__, flags, is_usb_dev, may_use_hifi_record,
8294 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308295
kunleizdff872d2018-08-20 14:40:33 +08008296 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008297 is_usb_dev = false;
8298 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8299 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8300 __func__, devices);
8301 }
8302
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008303 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008304
8305 if (!(is_usb_dev && may_use_hifi_record)) {
8306 if (config->sample_rate == 0)
8307 config->sample_rate = 48000;
8308 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8309 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8310 if (config->format == AUDIO_FORMAT_DEFAULT)
8311 config->format = AUDIO_FORMAT_PCM_16_BIT;
8312
8313 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8314
Aalique Grahame22e49102018-12-18 14:23:57 -08008315 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8316 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008317 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308318 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008319
8320 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008321
8322 if (!in) {
8323 ALOGE("failed to allocate input stream");
8324 return -ENOMEM;
8325 }
8326
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308327 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308328 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8329 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008330 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008331 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008332
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008333 in->stream.common.get_sample_rate = in_get_sample_rate;
8334 in->stream.common.set_sample_rate = in_set_sample_rate;
8335 in->stream.common.get_buffer_size = in_get_buffer_size;
8336 in->stream.common.get_channels = in_get_channels;
8337 in->stream.common.get_format = in_get_format;
8338 in->stream.common.set_format = in_set_format;
8339 in->stream.common.standby = in_standby;
8340 in->stream.common.dump = in_dump;
8341 in->stream.common.set_parameters = in_set_parameters;
8342 in->stream.common.get_parameters = in_get_parameters;
8343 in->stream.common.add_audio_effect = in_add_audio_effect;
8344 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8345 in->stream.set_gain = in_set_gain;
8346 in->stream.read = in_read;
8347 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008348 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308349 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008350 in->stream.set_microphone_direction = in_set_microphone_direction;
8351 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008352 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008353
8354 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008355 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008356 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008357 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008358 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008359 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008360 in->bit_width = 16;
8361 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008362 in->direction = MIC_DIRECTION_UNSPECIFIED;
8363 in->zoom = 0;
Haynes Mathew George46740472017-10-27 18:40:12 -07008364
Andy Hung94320602018-10-29 18:31:12 -07008365 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008366 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8367 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8368 /* Force channel config requested to mono if incall
8369 record is being requested for only uplink/downlink */
8370 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8371 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8372 ret = -EINVAL;
8373 goto err_open;
8374 }
8375 }
8376
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008377 if (is_usb_dev && may_use_hifi_record) {
8378 /* HiFi record selects an appropriate format, channel, rate combo
8379 depending on sink capabilities*/
8380 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8381 &config->format,
8382 &in->supported_formats[0],
8383 MAX_SUPPORTED_FORMATS,
8384 &config->channel_mask,
8385 &in->supported_channel_masks[0],
8386 MAX_SUPPORTED_CHANNEL_MASKS,
8387 &config->sample_rate,
8388 &in->supported_sample_rates[0],
8389 MAX_SUPPORTED_SAMPLE_RATES);
8390 if (ret != 0) {
8391 ret = -EINVAL;
8392 goto err_open;
8393 }
8394 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008395 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308396 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308397 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8398 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8399 in->config.format = PCM_FORMAT_S32_LE;
8400 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308401 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8402 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8403 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8404 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8405 bool ret_error = false;
8406 in->bit_width = 24;
8407 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8408 from HAL is 24_packed and 8_24
8409 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8410 24_packed return error indicating supported format is 24_packed
8411 *> In case of any other source requesting 24 bit or float return error
8412 indicating format supported is 16 bit only.
8413
8414 on error flinger will retry with supported format passed
8415 */
8416 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8417 (source != AUDIO_SOURCE_CAMCORDER)) {
8418 config->format = AUDIO_FORMAT_PCM_16_BIT;
8419 if (config->sample_rate > 48000)
8420 config->sample_rate = 48000;
8421 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008422 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8423 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308424 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8425 ret_error = true;
8426 }
8427
8428 if (ret_error) {
8429 ret = -EINVAL;
8430 goto err_open;
8431 }
8432 }
8433
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008434 in->channel_mask = config->channel_mask;
8435 in->format = config->format;
8436
8437 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308438
8439 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8440 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8441 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8442 else {
8443 ret = -EINVAL;
8444 goto err_open;
8445 }
8446 }
8447
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008448 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8449 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8450 is_low_latency = true;
8451#if LOW_LATENCY_CAPTURE_USE_CASE
8452 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8453#endif
8454 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008455 if (!in->realtime) {
8456 in->config = pcm_config_audio_capture;
8457 frame_size = audio_stream_in_frame_size(&in->stream);
8458 buffer_size = get_input_buffer_size(config->sample_rate,
8459 config->format,
8460 channel_count,
8461 is_low_latency);
8462 in->config.period_size = buffer_size / frame_size;
8463 in->config.rate = config->sample_rate;
8464 in->af_period_multiplier = 1;
8465 } else {
8466 // period size is left untouched for rt mode playback
8467 in->config = pcm_config_audio_capture_rt;
8468 in->af_period_multiplier = af_period_multiplier;
8469 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008470 }
8471
8472 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8473 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8474 in->realtime = 0;
8475 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8476 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008477 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008478 in->stream.start = in_start;
8479 in->stream.stop = in_stop;
8480 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8481 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008482 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8483 } else if (in->realtime) {
8484 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008485 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008486 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008487 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008488 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8489 in->config = pcm_config_audio_capture;
8490 frame_size = audio_stream_in_frame_size(&in->stream);
8491 buffer_size = get_input_buffer_size(config->sample_rate,
8492 config->format,
8493 channel_count,
8494 false /*is_low_latency*/);
8495 in->config.period_size = buffer_size / frame_size;
8496 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008497 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008498 switch (config->format) {
8499 case AUDIO_FORMAT_PCM_32_BIT:
8500 in->bit_width = 32;
8501 break;
8502 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8503 case AUDIO_FORMAT_PCM_8_24_BIT:
8504 in->bit_width = 24;
8505 break;
8506 default:
8507 in->bit_width = 16;
8508 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008509 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308510 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008511 if (config->sample_rate == 0)
8512 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8513 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8514 config->sample_rate != 8000) {
8515 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8516 ret = -EINVAL;
8517 goto err_open;
8518 }
8519 if (config->format == AUDIO_FORMAT_DEFAULT)
8520 config->format = AUDIO_FORMAT_PCM_16_BIT;
8521 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8522 config->format = AUDIO_FORMAT_PCM_16_BIT;
8523 ret = -EINVAL;
8524 goto err_open;
8525 }
8526
8527 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8528 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008529 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008530 in->af_period_multiplier = 1;
8531 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8532 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8533 (config->sample_rate == 8000 ||
8534 config->sample_rate == 16000 ||
8535 config->sample_rate == 32000 ||
8536 config->sample_rate == 48000) &&
8537 channel_count == 1) {
8538 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8539 in->config = pcm_config_audio_capture;
8540 frame_size = audio_stream_in_frame_size(&in->stream);
8541 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8542 config->sample_rate,
8543 config->format,
8544 channel_count, false /*is_low_latency*/);
8545 in->config.period_size = buffer_size / frame_size;
8546 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8547 in->config.rate = config->sample_rate;
8548 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008549 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308550 int ret_val;
8551 pthread_mutex_lock(&adev->lock);
8552 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8553 in, config, &channel_mask_updated);
8554 pthread_mutex_unlock(&adev->lock);
8555
8556 if (!ret_val) {
8557 if (channel_mask_updated == true) {
8558 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8559 __func__, config->channel_mask);
8560 ret = -EINVAL;
8561 goto err_open;
8562 }
8563 ALOGD("%s: created multi-channel session succesfully",__func__);
8564 } else if (audio_extn_compr_cap_enabled() &&
8565 audio_extn_compr_cap_format_supported(config->format) &&
8566 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8567 audio_extn_compr_cap_init(in);
8568 } else if (audio_extn_cin_applicable_stream(in)) {
8569 ret = audio_extn_cin_configure_input_stream(in);
8570 if (ret)
8571 goto err_open;
8572 } else {
8573 in->config = pcm_config_audio_capture;
8574 in->config.rate = config->sample_rate;
8575 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308576 in->format = config->format;
8577 frame_size = audio_stream_in_frame_size(&in->stream);
8578 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008579 config->format,
8580 channel_count,
8581 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008582 /* prevent division-by-zero */
8583 if (frame_size == 0) {
8584 ALOGE("%s: Error frame_size==0", __func__);
8585 ret = -EINVAL;
8586 goto err_open;
8587 }
8588
Revathi Uddarajud2634032017-12-07 14:42:34 +05308589 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008590 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008591
Revathi Uddarajud2634032017-12-07 14:42:34 +05308592 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8593 /* optionally use VOIP usecase depending on config(s) */
8594 ret = adev_update_voice_comm_input_stream(in, config);
8595 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008596
Revathi Uddarajud2634032017-12-07 14:42:34 +05308597 if (ret) {
8598 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8599 goto err_open;
8600 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008601 }
Samyak Jainc37062f2019-04-25 18:41:06 +05308602 if (audio_extn_is_concurrent_capture_enabled()) {
8603 /* Acquire lock to avoid two concurrent use cases initialized to
8604 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08008605
Samyak Jainc37062f2019-04-25 18:41:06 +05308606 if (in->usecase == USECASE_AUDIO_RECORD) {
8607 pthread_mutex_lock(&adev->lock);
8608 if (!(adev->pcm_record_uc_state)) {
8609 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8610 adev->pcm_record_uc_state = 1;
8611 pthread_mutex_unlock(&adev->lock);
8612 } else {
8613 pthread_mutex_unlock(&adev->lock);
8614 /* Assign compress record use case for second record */
8615 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8616 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8617 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8618 if (audio_extn_cin_applicable_stream(in)) {
8619 in->sample_rate = config->sample_rate;
8620 ret = audio_extn_cin_configure_input_stream(in);
8621 if (ret)
8622 goto err_open;
8623 }
8624 }
8625 }
kunleiz28c73e72019-03-27 17:24:04 +08008626 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008627 }
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008628
8629 in->config.channels = channel_count;
8630 in->sample_rate = in->config.rate;
8631
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308632 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8633 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008634 devices, flags, in->format,
8635 in->sample_rate, in->bit_width,
8636 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308637 register_format(in->format, in->supported_formats);
8638 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8639 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308640
Aalique Grahame22e49102018-12-18 14:23:57 -08008641 in->error_log = error_log_create(
8642 ERROR_LOG_ENTRIES,
8643 1000000000 /* aggregate consecutive identical errors within one second */);
8644
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008645 /* This stream could be for sound trigger lab,
8646 get sound trigger pcm if present */
8647 audio_extn_sound_trigger_check_and_get_session(in);
8648
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308649 lock_input_stream(in);
8650 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8651 pthread_mutex_lock(&adev->lock);
8652 in->card_status = adev->card_status;
8653 pthread_mutex_unlock(&adev->lock);
8654 pthread_mutex_unlock(&in->lock);
8655
Aalique Grahame22e49102018-12-18 14:23:57 -08008656 stream_app_type_cfg_init(&in->app_type_cfg);
8657
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008658 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008659
8660 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8661 calloc(1, sizeof(streams_input_ctxt_t));
8662 if (in_ctxt == NULL) {
8663 ALOGE("%s fail to allocate input ctxt", __func__);
8664 ret = -ENOMEM;
8665 goto err_open;
8666 }
8667 in_ctxt->input = in;
8668
8669 pthread_mutex_lock(&adev->lock);
8670 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8671 pthread_mutex_unlock(&adev->lock);
8672
Eric Laurent994a6932013-07-17 11:51:42 -07008673 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008674 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008675
8676err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05308677 if (in->usecase == USECASE_AUDIO_RECORD) {
8678 pthread_mutex_lock(&adev->lock);
8679 adev->pcm_record_uc_state = 0;
8680 pthread_mutex_unlock(&adev->lock);
8681 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008682 free(in);
8683 *stream_in = NULL;
8684 return ret;
8685}
8686
8687static void adev_close_input_stream(struct audio_hw_device *dev,
8688 struct audio_stream_in *stream)
8689{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008690 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008691 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008692 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308693
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308694 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008695
kunleiz70e57612018-12-28 17:50:23 +08008696 /* must deregister from sndmonitor first to prevent races
8697 * between the callback and close_stream
8698 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308699 audio_extn_snd_mon_unregister_listener(stream);
8700
kunleiz70e57612018-12-28 17:50:23 +08008701 /* Disable echo reference if there are no active input, hfp call
8702 * and sound trigger while closing input stream
8703 */
Eric Laurent637e2d42018-11-15 12:24:31 -08008704 if (adev_get_active_input(adev) == NULL &&
kunleiz70e57612018-12-28 17:50:23 +08008705 !audio_extn_hfp_is_active(adev) &&
8706 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008707 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008708 else
8709 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308710
Pallavid7c7a272018-01-16 11:22:55 +05308711 if (in == NULL) {
8712 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8713 return;
8714 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08008715 error_log_destroy(in->error_log);
8716 in->error_log = NULL;
8717
Pallavid7c7a272018-01-16 11:22:55 +05308718
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008719 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308720 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008721 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308722 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008723 if (ret != 0)
8724 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8725 __func__, ret);
8726 } else
8727 in_standby(&stream->common);
8728
Revathi Uddarajud2634032017-12-07 14:42:34 +05308729 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308730 if (in->usecase == USECASE_AUDIO_RECORD) {
8731 adev->pcm_record_uc_state = 0;
8732 }
8733
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008734 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008735 audio_extn_ssr_deinit();
8736 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008737
Garmond Leunge2433c32017-09-28 21:51:22 -07008738 if (audio_extn_ffv_get_stream() == in) {
8739 audio_extn_ffv_stream_deinit();
8740 }
8741
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308742 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008743 audio_extn_compr_cap_format_supported(in->config.format))
8744 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308745
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308746 if (audio_extn_cin_attached_usecase(in->usecase))
8747 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008748
Mingming Yinfd7607b2016-01-22 12:48:44 -08008749 if (in->is_st_session) {
8750 ALOGV("%s: sound trigger pcm stop lab", __func__);
8751 audio_extn_sound_trigger_stop_lab(in);
8752 }
Derek Chenf939fb72018-11-13 13:34:41 -08008753 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8754 if (in_ctxt != NULL) {
8755 list_remove(&in_ctxt->list);
8756 free(in_ctxt);
8757 } else {
8758 ALOGW("%s, input stream already closed", __func__);
8759 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008760 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308761 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008762 return;
8763}
8764
Aalique Grahame22e49102018-12-18 14:23:57 -08008765/* verifies input and output devices and their capabilities.
8766 *
8767 * This verification is required when enabling extended bit-depth or
8768 * sampling rates, as not all qcom products support it.
8769 *
8770 * Suitable for calling only on initialization such as adev_open().
8771 * It fills the audio_device use_case_table[] array.
8772 *
8773 * Has a side-effect that it needs to configure audio routing / devices
8774 * in order to power up the devices and read the device parameters.
8775 * It does not acquire any hw device lock. Should restore the devices
8776 * back to "normal state" upon completion.
8777 */
8778static int adev_verify_devices(struct audio_device *adev)
8779{
8780 /* enumeration is a bit difficult because one really wants to pull
8781 * the use_case, device id, etc from the hidden pcm_device_table[].
8782 * In this case there are the following use cases and device ids.
8783 *
8784 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8785 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8786 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8787 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8788 * [USECASE_AUDIO_RECORD] = {0, 0},
8789 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8790 * [USECASE_VOICE_CALL] = {2, 2},
8791 *
8792 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8793 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8794 */
8795
8796 /* should be the usecases enabled in adev_open_input_stream() */
8797 static const int test_in_usecases[] = {
8798 USECASE_AUDIO_RECORD,
8799 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8800 };
8801 /* should be the usecases enabled in adev_open_output_stream()*/
8802 static const int test_out_usecases[] = {
8803 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8804 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8805 };
8806 static const usecase_type_t usecase_type_by_dir[] = {
8807 PCM_PLAYBACK,
8808 PCM_CAPTURE,
8809 };
8810 static const unsigned flags_by_dir[] = {
8811 PCM_OUT,
8812 PCM_IN,
8813 };
8814
8815 size_t i;
8816 unsigned dir;
8817 const unsigned card_id = adev->snd_card;
8818
8819 for (dir = 0; dir < 2; ++dir) {
8820 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8821 const unsigned flags_dir = flags_by_dir[dir];
8822 const size_t testsize =
8823 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8824 const int *testcases =
8825 dir ? test_in_usecases : test_out_usecases;
8826 const audio_devices_t audio_device =
8827 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8828
8829 for (i = 0; i < testsize; ++i) {
8830 const audio_usecase_t audio_usecase = testcases[i];
8831 int device_id;
8832 struct pcm_params **pparams;
8833 struct stream_out out;
8834 struct stream_in in;
8835 struct audio_usecase uc_info;
8836 int retval;
8837
8838 pparams = &adev->use_case_table[audio_usecase];
8839 pcm_params_free(*pparams); /* can accept null input */
8840 *pparams = NULL;
8841
8842 /* find the device ID for the use case (signed, for error) */
8843 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8844 if (device_id < 0)
8845 continue;
8846
8847 /* prepare structures for device probing */
8848 memset(&uc_info, 0, sizeof(uc_info));
8849 uc_info.id = audio_usecase;
8850 uc_info.type = usecase_type;
8851 if (dir) {
Aalique Grahame22e49102018-12-18 14:23:57 -08008852 memset(&in, 0, sizeof(in));
8853 in.device = audio_device;
8854 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8855 uc_info.stream.in = &in;
Aalique Grahame22e49102018-12-18 14:23:57 -08008856 }
8857 memset(&out, 0, sizeof(out));
8858 out.devices = audio_device; /* only field needed in select_devices */
8859 uc_info.stream.out = &out;
8860 uc_info.devices = audio_device;
8861 uc_info.in_snd_device = SND_DEVICE_NONE;
8862 uc_info.out_snd_device = SND_DEVICE_NONE;
8863 list_add_tail(&adev->usecase_list, &uc_info.list);
8864
8865 /* select device - similar to start_(in/out)put_stream() */
8866 retval = select_devices(adev, audio_usecase);
8867 if (retval >= 0) {
8868 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8869#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07008870 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08008871 if (*pparams) {
8872 ALOGV("%s: (%s) card %d device %d", __func__,
8873 dir ? "input" : "output", card_id, device_id);
8874 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8875 } else {
8876 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8877 }
8878#endif
8879 }
8880
8881 /* deselect device - similar to stop_(in/out)put_stream() */
8882 /* 1. Get and set stream specific mixer controls */
8883 retval = disable_audio_route(adev, &uc_info);
8884 /* 2. Disable the rx device */
8885 retval = disable_snd_device(adev,
8886 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8887 list_remove(&uc_info.list);
8888 }
8889 }
Aalique Grahame22e49102018-12-18 14:23:57 -08008890 return 0;
8891}
8892
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308893int adev_create_audio_patch(struct audio_hw_device *dev,
8894 unsigned int num_sources,
8895 const struct audio_port_config *sources,
8896 unsigned int num_sinks,
8897 const struct audio_port_config *sinks,
8898 audio_patch_handle_t *handle)
8899{
Derek Chenf939fb72018-11-13 13:34:41 -08008900 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308901
Derek Chenf939fb72018-11-13 13:34:41 -08008902 ret = audio_extn_hw_loopback_create_audio_patch(dev,
8903 num_sources,
8904 sources,
8905 num_sinks,
8906 sinks,
8907 handle);
8908 ret |= audio_extn_auto_hal_create_audio_patch(dev,
8909 num_sources,
8910 sources,
8911 num_sinks,
8912 sinks,
8913 handle);
8914 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308915}
8916
8917int adev_release_audio_patch(struct audio_hw_device *dev,
8918 audio_patch_handle_t handle)
8919{
Derek Chenf939fb72018-11-13 13:34:41 -08008920 int ret;
8921
8922 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
8923 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
8924 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308925}
8926
8927int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8928{
8929 return audio_extn_hw_loopback_get_audio_port(dev, config);
8930}
8931
8932int adev_set_audio_port_config(struct audio_hw_device *dev,
8933 const struct audio_port_config *config)
8934{
8935 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8936}
8937
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008938static int adev_dump(const audio_hw_device_t *device __unused,
8939 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008940{
8941 return 0;
8942}
8943
8944static int adev_close(hw_device_t *device)
8945{
Aalique Grahame22e49102018-12-18 14:23:57 -08008946 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008947 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008948
8949 if (!adev)
8950 return 0;
8951
8952 pthread_mutex_lock(&adev_init_lock);
8953
8954 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05308955 if (audio_extn_spkr_prot_is_enabled())
8956 audio_extn_spkr_prot_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308957 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008958 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008959 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008960 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008961 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308962 audio_extn_utils_release_streams_cfg_lists(
8963 &adev->streams_output_cfg_list,
8964 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308965 if (audio_extn_qaf_is_enabled())
8966 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008967 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08008968 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07008969 free(adev->snd_dev_ref_cnt);
8970 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008971 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8972 pcm_params_free(adev->use_case_table[i]);
8973 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008974 if (adev->adm_deinit)
8975 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308976 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008977 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308978 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308979 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008980 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308981 if (adev->device_cfg_params) {
8982 free(adev->device_cfg_params);
8983 adev->device_cfg_params = NULL;
8984 }
Derek Chend2530072014-11-24 12:39:14 -08008985 if(adev->ext_hw_plugin)
8986 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08008987 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008988 free(device);
8989 adev = NULL;
8990 }
8991 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308992 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008993 return 0;
8994}
8995
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008996/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8997 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8998 * just that it _might_ work.
8999 */
9000static int period_size_is_plausible_for_low_latency(int period_size)
9001{
9002 switch (period_size) {
9003 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07009004 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009005 case 240:
9006 case 320:
9007 case 480:
9008 return 1;
9009 default:
9010 return 0;
9011 }
9012}
9013
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309014static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
9015{
9016 bool is_snd_card_status = false;
9017 bool is_ext_device_status = false;
9018 char value[32];
9019 int card = -1;
9020 card_status_t status;
9021
9022 if (cookie != adev || !parms)
9023 return;
9024
9025 if (!parse_snd_card_status(parms, &card, &status)) {
9026 is_snd_card_status = true;
9027 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9028 is_ext_device_status = true;
9029 } else {
9030 // not a valid event
9031 return;
9032 }
9033
9034 pthread_mutex_lock(&adev->lock);
9035 if (card == adev->snd_card || is_ext_device_status) {
9036 if (is_snd_card_status && adev->card_status != status) {
9037 adev->card_status = status;
9038 platform_snd_card_update(adev->platform, status);
9039 audio_extn_fm_set_parameters(adev, parms);
9040 } else if (is_ext_device_status) {
9041 platform_set_parameters(adev->platform, parms);
9042 }
9043 }
9044 pthread_mutex_unlock(&adev->lock);
9045 return;
9046}
9047
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309048/* out and adev lock held */
9049static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9050{
9051 struct audio_usecase *uc_info;
9052 float left_p;
9053 float right_p;
9054 audio_devices_t devices;
9055
9056 uc_info = get_usecase_from_list(adev, out->usecase);
9057 if (uc_info == NULL) {
9058 ALOGE("%s: Could not find the usecase (%d) in the list",
9059 __func__, out->usecase);
9060 return -EINVAL;
9061 }
9062
9063 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9064 out->usecase, use_case_table[out->usecase]);
9065
9066 if (restore) {
9067 // restore A2DP device for active usecases and unmute if required
9068 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9069 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9070 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9071 select_devices(adev, uc_info->id);
9072 pthread_mutex_lock(&out->compr_mute_lock);
9073 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9074 (out->a2dp_compress_mute)) {
9075 out->a2dp_compress_mute = false;
9076 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9077 }
9078 pthread_mutex_unlock(&out->compr_mute_lock);
9079 }
9080 } else {
9081 // mute compress stream if suspended
9082 pthread_mutex_lock(&out->compr_mute_lock);
9083 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9084 (!out->a2dp_compress_mute)) {
9085 if (!out->standby) {
9086 ALOGD("%s: selecting speaker and muting stream", __func__);
9087 devices = out->devices;
9088 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9089 left_p = out->volume_l;
9090 right_p = out->volume_r;
9091 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9092 compress_pause(out->compr);
9093 out_set_compr_volume(&out->stream, (float)0, (float)0);
9094 out->a2dp_compress_mute = true;
9095 select_devices(adev, out->usecase);
9096 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9097 compress_resume(out->compr);
9098 out->devices = devices;
9099 out->volume_l = left_p;
9100 out->volume_r = right_p;
9101 }
9102 }
9103 pthread_mutex_unlock(&out->compr_mute_lock);
9104 }
9105 ALOGV("%s: exit", __func__);
9106 return 0;
9107}
9108
9109int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9110{
9111 int ret = 0;
9112
9113 lock_output_stream(out);
9114 pthread_mutex_lock(&adev->lock);
9115
9116 ret = check_a2dp_restore_l(adev, out, restore);
9117
9118 pthread_mutex_unlock(&adev->lock);
9119 pthread_mutex_unlock(&out->lock);
9120 return ret;
9121}
9122
Haynes Mathew George01156f92018-04-13 15:29:54 -07009123void adev_on_battery_status_changed(bool charging)
9124{
9125 pthread_mutex_lock(&adev->lock);
9126 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9127 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009128 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009129 pthread_mutex_unlock(&adev->lock);
9130}
9131
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009132static int adev_open(const hw_module_t *module, const char *name,
9133 hw_device_t **device)
9134{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309135 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009136 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309137 char mixer_ctl_name[128] = {0};
9138 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309139
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009140 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009141 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9142
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009143 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009144 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009145 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009146 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009147 ALOGD("%s: returning existing instance of adev", __func__);
9148 ALOGD("%s: exit", __func__);
9149 pthread_mutex_unlock(&adev_init_lock);
9150 return 0;
9151 }
9152
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009153 adev = calloc(1, sizeof(struct audio_device));
9154
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009155 if (!adev) {
9156 pthread_mutex_unlock(&adev_init_lock);
9157 return -ENOMEM;
9158 }
9159
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009160 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9161
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009162 // register audio ext hidl at the earliest
9163 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309164#ifdef DYNAMIC_LOG_ENABLED
9165 register_for_dynamic_logging("hal");
9166#endif
9167
Derek Chenf939fb72018-11-13 13:34:41 -08009168 /* default audio HAL major version */
9169 uint32_t maj_version = 2;
9170 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9171 maj_version = atoi(value);
9172
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009173 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009174 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009175 adev->device.common.module = (struct hw_module_t *)module;
9176 adev->device.common.close = adev_close;
9177
9178 adev->device.init_check = adev_init_check;
9179 adev->device.set_voice_volume = adev_set_voice_volume;
9180 adev->device.set_master_volume = adev_set_master_volume;
9181 adev->device.get_master_volume = adev_get_master_volume;
9182 adev->device.set_master_mute = adev_set_master_mute;
9183 adev->device.get_master_mute = adev_get_master_mute;
9184 adev->device.set_mode = adev_set_mode;
9185 adev->device.set_mic_mute = adev_set_mic_mute;
9186 adev->device.get_mic_mute = adev_get_mic_mute;
9187 adev->device.set_parameters = adev_set_parameters;
9188 adev->device.get_parameters = adev_get_parameters;
9189 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9190 adev->device.open_output_stream = adev_open_output_stream;
9191 adev->device.close_output_stream = adev_close_output_stream;
9192 adev->device.open_input_stream = adev_open_input_stream;
9193 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309194 adev->device.create_audio_patch = adev_create_audio_patch;
9195 adev->device.release_audio_patch = adev_release_audio_patch;
9196 adev->device.get_audio_port = adev_get_audio_port;
9197 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009198 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309199 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009200
9201 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009202 adev->mode = AUDIO_MODE_NORMAL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009203 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009204 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009205 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009206 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009207 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309208 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009209 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009210 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009211 /* Init audio and voice feature */
9212 audio_extn_feature_init();
9213 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009214 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009215 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009216 list_init(&adev->active_inputs_list);
9217 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009218 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009219 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309220 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309221 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309222 adev->perf_lock_opts[0] = 0x101;
9223 adev->perf_lock_opts[1] = 0x20E;
9224 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009225 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009226 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309227 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009228 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009230 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009231 adev->platform = platform_init(adev);
9232 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009233 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009234 free(adev->snd_dev_ref_cnt);
9235 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009236 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009237 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9238 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009239 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009240 return -EINVAL;
9241 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009242
Aalique Grahame22e49102018-12-18 14:23:57 -08009243 adev->extspk = audio_extn_extspk_init(adev);
9244
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309245 if (audio_extn_qaf_is_enabled()) {
9246 ret = audio_extn_qaf_init(adev);
9247 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009248 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309249 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009250 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309251 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9252 *device = NULL;
9253 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309254 return ret;
9255 }
9256
9257 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9258 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9259 }
9260
Derek Chenae7b0342019-02-08 15:17:04 -08009261 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009262 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9263
Eric Laurentc4aef752013-09-12 17:45:53 -07009264 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9265 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9266 if (adev->visualizer_lib == NULL) {
9267 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9268 } else {
9269 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9270 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009271 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009272 "visualizer_hal_start_output");
9273 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009274 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009275 "visualizer_hal_stop_output");
9276 }
9277 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309278 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009279 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009280 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009281 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309282 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009283 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009284
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009285 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9286 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9287 if (adev->offload_effects_lib == NULL) {
9288 ALOGE("%s: DLOPEN failed for %s", __func__,
9289 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9290 } else {
9291 ALOGV("%s: DLOPEN successful for %s", __func__,
9292 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9293 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309294 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009295 "offload_effects_bundle_hal_start_output");
9296 adev->offload_effects_stop_output =
9297 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9298 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009299 adev->offload_effects_set_hpx_state =
9300 (int (*)(bool))dlsym(adev->offload_effects_lib,
9301 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309302 adev->offload_effects_get_parameters =
9303 (void (*)(struct str_parms *, struct str_parms *))
9304 dlsym(adev->offload_effects_lib,
9305 "offload_effects_bundle_get_parameters");
9306 adev->offload_effects_set_parameters =
9307 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9308 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009309 }
9310 }
9311
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009312 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9313 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9314 if (adev->adm_lib == NULL) {
9315 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9316 } else {
9317 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9318 adev->adm_init = (adm_init_t)
9319 dlsym(adev->adm_lib, "adm_init");
9320 adev->adm_deinit = (adm_deinit_t)
9321 dlsym(adev->adm_lib, "adm_deinit");
9322 adev->adm_register_input_stream = (adm_register_input_stream_t)
9323 dlsym(adev->adm_lib, "adm_register_input_stream");
9324 adev->adm_register_output_stream = (adm_register_output_stream_t)
9325 dlsym(adev->adm_lib, "adm_register_output_stream");
9326 adev->adm_deregister_stream = (adm_deregister_stream_t)
9327 dlsym(adev->adm_lib, "adm_deregister_stream");
9328 adev->adm_request_focus = (adm_request_focus_t)
9329 dlsym(adev->adm_lib, "adm_request_focus");
9330 adev->adm_abandon_focus = (adm_abandon_focus_t)
9331 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009332 adev->adm_set_config = (adm_set_config_t)
9333 dlsym(adev->adm_lib, "adm_set_config");
9334 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9335 dlsym(adev->adm_lib, "adm_request_focus_v2");
9336 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9337 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9338 adev->adm_on_routing_change = (adm_on_routing_change_t)
9339 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009340 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9341 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009342 }
9343 }
9344
Aalique Grahame22e49102018-12-18 14:23:57 -08009345 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009346 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009347 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009348 //initialize this to false for now,
9349 //this will be set to true through set param
9350 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009351
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009352 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009353 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009354
9355 if (k_enable_extended_precision)
9356 adev_verify_devices(adev);
9357
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009358 adev->dsp_bit_width_enforce_mode =
9359 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009360
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309361 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9362 &adev->streams_output_cfg_list,
9363 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009364
Kiran Kandi910e1862013-10-29 13:29:42 -07009365 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009366
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009367 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009368 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9369 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009370 trial = atoi(value);
9371 if (period_size_is_plausible_for_low_latency(trial)) {
9372 pcm_config_low_latency.period_size = trial;
9373 pcm_config_low_latency.start_threshold = trial / 4;
9374 pcm_config_low_latency.avail_min = trial / 4;
9375 configured_low_latency_capture_period_size = trial;
9376 }
9377 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009378 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9379 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009380 trial = atoi(value);
9381 if (period_size_is_plausible_for_low_latency(trial)) {
9382 configured_low_latency_capture_period_size = trial;
9383 }
9384 }
9385
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009386 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9387
Eric Laurent4b084132018-10-19 17:33:43 -07009388 adev->camera_orientation = CAMERA_DEFAULT;
9389
Aalique Grahame22e49102018-12-18 14:23:57 -08009390 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9391 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009392 af_period_multiplier = atoi(value);
9393 if (af_period_multiplier < 0)
9394 af_period_multiplier = 2;
9395 else if (af_period_multiplier > 4)
9396 af_period_multiplier = 4;
9397
9398 ALOGV("new period_multiplier = %d", af_period_multiplier);
9399 }
9400
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009401 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009402
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009403 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009404 pthread_mutex_unlock(&adev_init_lock);
9405
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009406 if (adev->adm_init)
9407 adev->adm_data = adev->adm_init();
9408
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309409 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309410 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009411 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309412
9413 audio_extn_snd_mon_init();
9414 pthread_mutex_lock(&adev->lock);
9415 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9416 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009417 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9418 /*
9419 * if the battery state callback happens before charging can be queried,
9420 * it will be guarded with the adev->lock held in the cb function and so
9421 * the callback value will reflect the latest state
9422 */
9423 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309424 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009425 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009426 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009427 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309428 /* Allocate memory for Device config params */
9429 adev->device_cfg_params = (struct audio_device_config_param*)
9430 calloc(platform_get_max_codec_backend(),
9431 sizeof(struct audio_device_config_param));
9432 if (adev->device_cfg_params == NULL)
9433 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309434
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309435 /*
9436 * Check if new PSPD matrix mixer control is supported. If not
9437 * supported, then set flag so that old mixer ctrl is sent while
9438 * sending pspd coefficients on older kernel version. Query mixer
9439 * control for default pcm id and channel value one.
9440 */
9441 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9442 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9443
9444 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9445 if (!ctl) {
9446 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9447 __func__, mixer_ctl_name);
9448 adev->use_old_pspd_mix_ctrl = true;
9449 }
9450
Eric Laurent994a6932013-07-17 11:51:42 -07009451 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009452 return 0;
9453}
9454
9455static struct hw_module_methods_t hal_module_methods = {
9456 .open = adev_open,
9457};
9458
9459struct audio_module HAL_MODULE_INFO_SYM = {
9460 .common = {
9461 .tag = HARDWARE_MODULE_TAG,
9462 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9463 .hal_api_version = HARDWARE_HAL_API_VERSION,
9464 .id = AUDIO_HARDWARE_MODULE_ID,
9465 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009466 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009467 .methods = &hal_module_methods,
9468 },
9469};