blob: 71b18b6c6e677ec98e130c4cf3db6f84ae9135a0 [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"
Eric Laurentb23d5282013-05-14 15:27:20 -070072#include "platform_api.h"
73#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070074#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080075#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053076#include "ip_hdlr_intf.h"
Arun Mirpurib1bec9c2019-01-29 16:42:45 -080077#include "audio_feature_manager.h"
justinweng20fb6d82019-02-21 18:49:00 -070078#include "audio_extn/audiozoom.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080079
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070080#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080081#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080082
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053083#ifdef DYNAMIC_LOG_ENABLED
84#include <log_xml_parser.h>
85#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
86#include <log_utils.h>
87#endif
88
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070089#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053090/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
91#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070092#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070093#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070094#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053095#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053096#define DSD_VOLUME_MIN_DB (-110)
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
587static void request_in_focus(struct stream_in *in, long ns)
588{
589 struct audio_device *adev = in->dev;
590
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700591 if (adev->adm_request_focus_v2)
592 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
593 else if (adev->adm_request_focus)
594 adev->adm_request_focus(adev->adm_data, in->capture_handle);
595}
596
597static void release_out_focus(struct stream_out *out)
598{
599 struct audio_device *adev = out->dev;
600
601 if (adev->adm_abandon_focus)
602 adev->adm_abandon_focus(adev->adm_data, out->handle);
603}
604
605static void release_in_focus(struct stream_in *in)
606{
607 struct audio_device *adev = in->dev;
608 if (adev->adm_abandon_focus)
609 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
610}
611
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530612static int parse_snd_card_status(struct str_parms *parms, int *card,
613 card_status_t *status)
614{
615 char value[32]={0};
616 char state[32]={0};
617
618 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
619 if (ret < 0)
620 return -1;
621
622 // sscanf should be okay as value is of max length 32.
623 // same as sizeof state.
624 if (sscanf(value, "%d,%s", card, state) < 2)
625 return -1;
626
627 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
628 CARD_STATUS_OFFLINE;
629 return 0;
630}
631
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700632static inline void adjust_frames_for_device_delay(struct stream_out *out,
633 uint32_t *dsp_frames) {
634 // Adjustment accounts for A2dp encoder latency with offload usecases
635 // Note: Encoder latency is returned in ms.
636 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
637 unsigned long offset =
638 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
639 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
640 }
641}
642
vivek mehtaa76401a2015-04-24 14:12:15 -0700643__attribute__ ((visibility ("default")))
644bool audio_hw_send_gain_dep_calibration(int level) {
645 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700646 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700647
648 pthread_mutex_lock(&adev_init_lock);
649
650 if (adev != NULL && adev->platform != NULL) {
651 pthread_mutex_lock(&adev->lock);
652 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700653
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530654 // cache level info for any of the use case which
655 // was not started.
656 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700657
vivek mehtaa76401a2015-04-24 14:12:15 -0700658 pthread_mutex_unlock(&adev->lock);
659 } else {
660 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
661 }
662
663 pthread_mutex_unlock(&adev_init_lock);
664
665 return ret_val;
666}
667
Ashish Jain5106d362016-05-11 19:23:33 +0530668static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
669{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800670 bool gapless_enabled = false;
671 const char *mixer_ctl_name = "Compress Gapless Playback";
672 struct mixer_ctl *ctl;
673
674 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700675 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530676
677 /*Disable gapless if its AV playback*/
678 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800679
680 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
681 if (!ctl) {
682 ALOGE("%s: Could not get ctl for mixer cmd - %s",
683 __func__, mixer_ctl_name);
684 return -EINVAL;
685 }
686
687 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
688 ALOGE("%s: Could not set gapless mode %d",
689 __func__, gapless_enabled);
690 return -EINVAL;
691 }
692 return 0;
693}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700694
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700695__attribute__ ((visibility ("default")))
696int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
697 int table_size) {
698 int ret_val = 0;
699 ALOGV("%s: enter ... ", __func__);
700
701 pthread_mutex_lock(&adev_init_lock);
702 if (adev == NULL) {
703 ALOGW("%s: adev is NULL .... ", __func__);
704 goto done;
705 }
706
707 pthread_mutex_lock(&adev->lock);
708 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
709 pthread_mutex_unlock(&adev->lock);
710done:
711 pthread_mutex_unlock(&adev_init_lock);
712 ALOGV("%s: exit ... ", __func__);
713 return ret_val;
714}
715
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800716bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800717{
718 bool ret = false;
719 ALOGV("%s: enter ...", __func__);
720
721 pthread_mutex_lock(&adev_init_lock);
722
723 if (adev != NULL && adev->platform != NULL) {
724 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800725 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800726 pthread_mutex_unlock(&adev->lock);
727 }
728
729 pthread_mutex_unlock(&adev_init_lock);
730
731 ALOGV("%s: exit with ret %d", __func__, ret);
732 return ret;
733}
Aalique Grahame22e49102018-12-18 14:23:57 -0800734
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700735static bool is_supported_format(audio_format_t format)
736{
Eric Laurent86e17132013-09-12 17:49:30 -0700737 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530738 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530739 format == AUDIO_FORMAT_AAC_LC ||
740 format == AUDIO_FORMAT_AAC_HE_V1 ||
741 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530742 format == AUDIO_FORMAT_AAC_ADTS_LC ||
743 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
744 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530745 format == AUDIO_FORMAT_AAC_LATM_LC ||
746 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
747 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530748 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
749 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530750 format == AUDIO_FORMAT_PCM_FLOAT ||
751 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700752 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530753 format == AUDIO_FORMAT_AC3 ||
754 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700755 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530756 format == AUDIO_FORMAT_DTS ||
757 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800758 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530759 format == AUDIO_FORMAT_ALAC ||
760 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530761 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530762 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800763 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530764 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700765 format == AUDIO_FORMAT_APTX ||
766 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800767 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700768
769 return false;
770}
771
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700772static inline bool is_mmap_usecase(audio_usecase_t uc_id)
773{
774 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
775 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
776}
777
Avinash Vaish71a8b972014-07-24 15:36:33 +0530778static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
779 struct audio_usecase *uc_info)
780{
781 struct listnode *node;
782 struct audio_usecase *usecase;
783
784 if (uc_info == NULL)
785 return -EINVAL;
786
787 /* Re-route all voice usecases on the shared backend other than the
788 specified usecase to new snd devices */
789 list_for_each(node, &adev->usecase_list) {
790 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800791 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530792 enable_audio_route(adev, usecase);
793 }
794 return 0;
795}
796
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530797static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530798{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530799 ALOGV("%s", __func__);
800 audio_route_apply_and_update_path(adev->audio_route,
801 "asrc-mode");
802 adev->asrc_mode_enabled = true;
803}
804
805static void disable_asrc_mode(struct audio_device *adev)
806{
807 ALOGV("%s", __func__);
808 audio_route_reset_and_update_path(adev->audio_route,
809 "asrc-mode");
810 adev->asrc_mode_enabled = false;
811}
812
813/*
814 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
815 * 44.1 or Native DSD backends are enabled for any of current use case.
816 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
817 * - Disable current mix path use case(Headphone backend) and re-enable it with
818 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
819 * e.g. Naitve DSD or Headphone 44.1 -> + 48
820 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530821static void check_and_set_asrc_mode(struct audio_device *adev,
822 struct audio_usecase *uc_info,
823 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530824{
825 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530826 int i, num_new_devices = 0;
827 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
828 /*
829 *Split snd device for new combo use case
830 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
831 */
832 if (platform_split_snd_device(adev->platform,
833 snd_device,
834 &num_new_devices,
835 split_new_snd_devices) == 0) {
836 for (i = 0; i < num_new_devices; i++)
837 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
838 } else {
839 int new_backend_idx = platform_get_backend_index(snd_device);
840 if (((new_backend_idx == HEADPHONE_BACKEND) ||
841 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
842 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
843 !adev->asrc_mode_enabled) {
844 struct listnode *node = NULL;
845 struct audio_usecase *uc = NULL;
846 struct stream_out *curr_out = NULL;
847 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
848 int i, num_devices, ret = 0;
849 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530850
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530851 list_for_each(node, &adev->usecase_list) {
852 uc = node_to_item(node, struct audio_usecase, list);
853 curr_out = (struct stream_out*) uc->stream.out;
854 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
855 /*
856 *Split snd device for existing combo use case
857 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
858 */
859 ret = platform_split_snd_device(adev->platform,
860 uc->out_snd_device,
861 &num_devices,
862 split_snd_devices);
863 if (ret < 0 || num_devices == 0) {
864 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
865 split_snd_devices[0] = uc->out_snd_device;
866 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800867 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530868 for (i = 0; i < num_devices; i++) {
869 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
870 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
871 if((new_backend_idx == HEADPHONE_BACKEND) &&
872 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
873 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
874 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
875 __func__);
876 enable_asrc_mode(adev);
877 break;
878 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
879 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
880 (usecase_backend_idx == HEADPHONE_BACKEND)) {
881 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
882 __func__);
883 disable_audio_route(adev, uc);
884 disable_snd_device(adev, uc->out_snd_device);
885 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
886 if (new_backend_idx == DSD_NATIVE_BACKEND)
887 audio_route_apply_and_update_path(adev->audio_route,
888 "hph-true-highquality-mode");
889 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
890 (curr_out->bit_width >= 24))
891 audio_route_apply_and_update_path(adev->audio_route,
892 "hph-highquality-mode");
893 enable_asrc_mode(adev);
894 enable_snd_device(adev, uc->out_snd_device);
895 enable_audio_route(adev, uc);
896 break;
897 }
898 }
899 // reset split devices count
900 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800901 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530902 if (adev->asrc_mode_enabled)
903 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530904 }
905 }
906 }
907}
908
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700909static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
910 struct audio_effect_config effect_config,
911 unsigned int param_value)
912{
913 char mixer_ctl_name[] = "Audio Effect";
914 struct mixer_ctl *ctl;
915 long set_values[6];
916 struct stream_in *in = adev->active_input;
917
918 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
919 if (!ctl) {
920 ALOGE("%s: Could not get mixer ctl - %s",
921 __func__, mixer_ctl_name);
922 return -EINVAL;
923 }
924
925 set_values[0] = 1; //0:Rx 1:Tx
926 set_values[1] = in->app_type_cfg.app_type;
927 set_values[2] = (long)effect_config.module_id;
928 set_values[3] = (long)effect_config.instance_id;
929 set_values[4] = (long)effect_config.param_id;
930 set_values[5] = param_value;
931
932 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
933
934 return 0;
935
936}
937
938static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
939 int effect_type, unsigned int *param_value)
940{
941 int ret = 0;
942 struct audio_effect_config other_effect_config;
943 struct audio_usecase *usecase = NULL;
944 struct stream_in *in = adev->active_input;
945
946 usecase = get_usecase_from_list(adev, in->usecase);
947 if (!usecase)
948 return -EINVAL;
949
950 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
951 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
952 if (ret < 0) {
953 ALOGE("%s Failed to get effect params %d", __func__, ret);
954 return ret;
955 }
956
957 if (module_id == other_effect_config.module_id) {
958 //Same module id for AEC/NS. Values need to be combined
959 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
960 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
961 *param_value |= other_effect_config.param_value;
962 }
963 }
964
965 return ret;
966}
967
968static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800969{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700970 struct audio_effect_config effect_config;
971 struct audio_usecase *usecase = NULL;
972 int ret = 0;
973 unsigned int param_value = 0;
974 struct stream_in *in = adev->active_input;
975
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800976 if(!voice_extn_is_dynamic_ecns_enabled())
977 return ENOSYS;
978
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700979 if (!in) {
980 ALOGE("%s: Invalid input stream", __func__);
981 return -EINVAL;
982 }
983
984 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
985
986 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800987 if (usecase == NULL) {
988 ALOGE("%s: Could not find the usecase (%d) in the list",
989 __func__, in->usecase);
990 return -EINVAL;
991 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700992
993 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
994 if (ret < 0) {
995 ALOGE("%s Failed to get module id %d", __func__, ret);
996 return ret;
997 }
998 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
999 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1000
1001 if(enable)
1002 param_value = effect_config.param_value;
1003
1004 /*Special handling for AEC & NS effects Param values need to be
1005 updated if module ids are same*/
1006
1007 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1008 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1009 if (ret < 0)
1010 return ret;
1011 }
1012
1013 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1014
1015 return ret;
1016}
1017
1018static void check_and_enable_effect(struct audio_device *adev)
1019{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001020 if(!voice_extn_is_dynamic_ecns_enabled())
1021 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001022
1023 if (adev->active_input->enable_aec) {
1024 enable_disable_effect(adev, EFFECT_AEC, true);
1025 }
1026
1027 if (adev->active_input->enable_ns &&
1028 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1029 enable_disable_effect(adev, EFFECT_NS, true);
1030 }
1031}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001032
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001033int pcm_ioctl(struct pcm *pcm, int request, ...)
1034{
1035 va_list ap;
1036 void * arg;
1037 int pcm_fd = *(int*)pcm;
1038
1039 va_start(ap, request);
1040 arg = va_arg(ap, void *);
1041 va_end(ap);
1042
1043 return ioctl(pcm_fd, request, arg);
1044}
1045
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001046int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001047 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001048{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001049 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001050 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301051 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301052 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001053
1054 if (usecase == NULL)
1055 return -EINVAL;
1056
1057 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1058
Surendar Karka93cd25a2018-08-28 14:21:37 +05301059 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001060 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001061 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001062 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001063
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001064#ifdef DS1_DOLBY_DAP_ENABLED
1065 audio_extn_dolby_set_dmid(adev);
1066 audio_extn_dolby_set_endpoint(adev);
1067#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001068 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001069 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301070 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001071 audio_extn_utils_send_app_type_cfg(adev, usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301072 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301073 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1074 out = usecase->stream.out;
1075 if (out && out->compr)
1076 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1077 }
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301078 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301079
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001080 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001081 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001082 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301083 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1084 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1085 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1086 if (parms) {
1087 audio_extn_fm_set_parameters(adev, parms);
1088 str_parms_destroy(parms);
1089 }
1090 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001091 ALOGV("%s: exit", __func__);
1092 return 0;
1093}
1094
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001095int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001096 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001097{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001098 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001099 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001100
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301101 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001102 return -EINVAL;
1103
1104 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301105 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001106 snd_device = usecase->in_snd_device;
1107 else
1108 snd_device = usecase->out_snd_device;
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08001109 strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
Banajit Goswami20cdd212015-09-11 01:11:30 -07001110 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001111 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001112 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001113 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301114 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301115 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301116 if (usecase->stream.out != NULL)
1117 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001118 ALOGV("%s: exit", __func__);
1119 return 0;
1120}
1121
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001122int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001123 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001124{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301125 int i, num_devices = 0;
1126 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001127 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1128
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001129 if (snd_device < SND_DEVICE_MIN ||
1130 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001131 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001132 return -EINVAL;
1133 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001134
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001135 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001136 ALOGE("%s: Invalid sound device returned", __func__);
1137 return -EINVAL;
1138 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001139
1140 adev->snd_dev_ref_cnt[snd_device]++;
1141
1142 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1143 (platform_split_snd_device(adev->platform,
1144 snd_device,
1145 &num_devices,
1146 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001147 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001148 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001149 return 0;
1150 }
1151
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001152 if (audio_extn_spkr_prot_is_enabled())
1153 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001154
Aalique Grahame22e49102018-12-18 14:23:57 -08001155 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1156
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001157 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1158 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001159 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1160 goto err;
1161 }
1162 audio_extn_dev_arbi_acquire(snd_device);
1163 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001164 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001165 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001166 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001167 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001168 } else if (platform_split_snd_device(adev->platform,
1169 snd_device,
1170 &num_devices,
1171 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301172 for (i = 0; i < num_devices; i++) {
1173 enable_snd_device(adev, new_snd_devices[i]);
1174 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001175 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001176 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001177 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301178
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301179
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001180 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1181 (audio_extn_a2dp_start_playback() < 0)) {
1182 ALOGE(" fail to configure A2dp Source control path ");
1183 goto err;
1184 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001185
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001186 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1187 (audio_extn_a2dp_start_capture() < 0)) {
1188 ALOGE(" fail to configure A2dp Sink control path ");
1189 goto err;
1190 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301191
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001192 /* due to the possibility of calibration overwrite between listen
1193 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001194 audio_extn_sound_trigger_update_device_status(snd_device,
1195 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301196 audio_extn_listen_update_device_status(snd_device,
1197 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001198 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001199 audio_extn_sound_trigger_update_device_status(snd_device,
1200 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301201 audio_extn_listen_update_device_status(snd_device,
1202 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001203 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001204 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001205 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001206 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301207
1208 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1209 !adev->native_playback_enabled &&
1210 audio_is_true_native_stream_active(adev)) {
1211 ALOGD("%s: %d: napb: enabling native mode in hardware",
1212 __func__, __LINE__);
1213 audio_route_apply_and_update_path(adev->audio_route,
1214 "true-native-mode");
1215 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301216 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301217 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1218 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001219 (audio_extn_ffv_get_stream() == adev->active_input)) {
1220 ALOGD("%s: init ec ref loopback", __func__);
1221 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1222 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001223 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001224 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001225err:
1226 adev->snd_dev_ref_cnt[snd_device]--;
1227 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001228}
1229
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001230int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001231 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001232{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301233 int i, num_devices = 0;
1234 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001235 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1236
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001237 if (snd_device < SND_DEVICE_MIN ||
1238 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001239 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001240 return -EINVAL;
1241 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001242
1243 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1244 ALOGE("%s: Invalid sound device returned", __func__);
1245 return -EINVAL;
1246 }
1247
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001248 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1249 ALOGE("%s: device ref cnt is already 0", __func__);
1250 return -EINVAL;
1251 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001252
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001253 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001254
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001255
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001256 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001257 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301258
Aalique Grahame22e49102018-12-18 14:23:57 -08001259 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1260
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001261 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1262 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001263 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001264
1265 // when speaker device is disabled, reset swap.
1266 // will be renabled on usecase start
1267 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001268 } else if (platform_split_snd_device(adev->platform,
1269 snd_device,
1270 &num_devices,
1271 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301272 for (i = 0; i < num_devices; i++) {
1273 disable_snd_device(adev, new_snd_devices[i]);
1274 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001275 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001276 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001277 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001278 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001279
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001280 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301281 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001282 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001283 audio_extn_a2dp_stop_capture();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001284 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
1285 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301286 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001287 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301288 adev->native_playback_enabled) {
1289 ALOGD("%s: %d: napb: disabling native mode in hardware",
1290 __func__, __LINE__);
1291 audio_route_reset_and_update_path(adev->audio_route,
1292 "true-native-mode");
1293 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001294 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301295 adev->asrc_mode_enabled) {
1296 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301297 disable_asrc_mode(adev);
1298 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001299 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301300 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001301 (audio_extn_ffv_get_stream() == adev->active_input)) {
1302 ALOGD("%s: deinit ec ref loopback", __func__);
1303 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1304 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001305
1306 audio_extn_utils_release_snd_device(snd_device);
1307 } else {
1308 if (platform_split_snd_device(adev->platform,
1309 snd_device,
1310 &num_devices,
1311 new_snd_devices) == 0) {
1312 for (i = 0; i < num_devices; i++) {
1313 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1314 }
1315 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001316 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001317
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001318 return 0;
1319}
1320
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001321/*
1322 legend:
1323 uc - existing usecase
1324 new_uc - new usecase
1325 d1, d11, d2 - SND_DEVICE enums
1326 a1, a2 - corresponding ANDROID device enums
1327 B1, B2 - backend strings
1328
1329case 1
1330 uc->dev d1 (a1) B1
1331 new_uc->dev d1 (a1), d2 (a2) B1, B2
1332
1333 resolution: disable and enable uc->dev on d1
1334
1335case 2
1336 uc->dev d1 (a1) B1
1337 new_uc->dev d11 (a1) B1
1338
1339 resolution: need to switch uc since d1 and d11 are related
1340 (e.g. speaker and voice-speaker)
1341 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1342
1343case 3
1344 uc->dev d1 (a1) B1
1345 new_uc->dev d2 (a2) B2
1346
1347 resolution: no need to switch uc
1348
1349case 4
1350 uc->dev d1 (a1) B1
1351 new_uc->dev d2 (a2) B1
1352
1353 resolution: disable enable uc-dev on d2 since backends match
1354 we cannot enable two streams on two different devices if they
1355 share the same backend. e.g. if offload is on speaker device using
1356 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1357 using the same backend, offload must also be switched to voice-handset.
1358
1359case 5
1360 uc->dev d1 (a1) B1
1361 new_uc->dev d1 (a1), d2 (a2) B1
1362
1363 resolution: disable enable uc-dev on d2 since backends match
1364 we cannot enable two streams on two different devices if they
1365 share the same backend.
1366
1367case 6
1368 uc->dev d1 (a1) B1
1369 new_uc->dev d2 (a1) B2
1370
1371 resolution: no need to switch
1372
1373case 7
1374 uc->dev d1 (a1), d2 (a2) B1, B2
1375 new_uc->dev d1 (a1) B1
1376
1377 resolution: no need to switch
1378
Zhou Song4ba65882018-07-09 14:48:07 +08001379case 8
1380 uc->dev d1 (a1) B1
1381 new_uc->dev d11 (a1), d2 (a2) B1, B2
1382 resolution: compared to case 1, for this case, d1 and d11 are related
1383 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001384*/
1385static snd_device_t derive_playback_snd_device(void * platform,
1386 struct audio_usecase *uc,
1387 struct audio_usecase *new_uc,
1388 snd_device_t new_snd_device)
1389{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301390 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001391
1392 snd_device_t d1 = uc->out_snd_device;
1393 snd_device_t d2 = new_snd_device;
1394
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301395 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301396 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301397 a1 = uc->stream.inout->out_config.devices;
1398 a2 = new_uc->stream.inout->out_config.devices;
1399 break;
1400 default :
1401 a1 = uc->stream.out->devices;
1402 a2 = new_uc->stream.out->devices;
1403 break;
1404 }
1405
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001406 // Treat as a special case when a1 and a2 are not disjoint
1407 if ((a1 != a2) && (a1 & a2)) {
1408 snd_device_t d3[2];
1409 int num_devices = 0;
1410 int ret = platform_split_snd_device(platform,
1411 popcount(a1) > 1 ? d1 : d2,
1412 &num_devices,
1413 d3);
1414 if (ret < 0) {
1415 if (ret != -ENOSYS) {
1416 ALOGW("%s failed to split snd_device %d",
1417 __func__,
1418 popcount(a1) > 1 ? d1 : d2);
1419 }
1420 goto end;
1421 }
1422
1423 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1424 // But if it does happen, we need to give priority to d2 if
1425 // the combo devices active on the existing usecase share a backend.
1426 // This is because we cannot have a usecase active on a combo device
1427 // and a new usecase requests one device in this combo pair.
1428 if (platform_check_backends_match(d3[0], d3[1])) {
1429 return d2; // case 5
1430 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001431 // check if d1 is related to any of d3's
1432 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001433 return d1; // case 1
1434 else
1435 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001436 }
1437 } else {
1438 if (platform_check_backends_match(d1, d2)) {
1439 return d2; // case 2, 4
1440 } else {
1441 return d1; // case 6, 3
1442 }
1443 }
1444
1445end:
1446 return d2; // return whatever was calculated before.
1447}
1448
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001449static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301450 struct audio_usecase *uc_info,
1451 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001452{
1453 struct listnode *node;
1454 struct audio_usecase *usecase;
1455 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301456 snd_device_t uc_derive_snd_device;
1457 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001458 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1459 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001460 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301461 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001462 /*
1463 * This function is to make sure that all the usecases that are active on
1464 * the hardware codec backend are always routed to any one device that is
1465 * handled by the hardware codec.
1466 * For example, if low-latency and deep-buffer usecases are currently active
1467 * on speaker and out_set_parameters(headset) is received on low-latency
1468 * output, then we have to make sure deep-buffer is also switched to headset,
1469 * because of the limitation that both the devices cannot be enabled
1470 * at the same time as they share the same backend.
1471 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001472 /*
1473 * This call is to check if we need to force routing for a particular stream
1474 * If there is a backend configuration change for the device when a
1475 * new stream starts, then ADM needs to be closed and re-opened with the new
1476 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001477 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001478 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001479 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1480 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301481 /* For a2dp device reconfigure all active sessions
1482 * with new AFE encoder format based on a2dp state
1483 */
1484 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1485 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1486 audio_extn_a2dp_is_force_device_switch()) {
1487 force_routing = true;
1488 force_restart_session = true;
1489 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301490 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1491
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001492 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001493 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001494 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001495 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1496 switch_device[i] = false;
1497
1498 list_for_each(node, &adev->usecase_list) {
1499 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001500
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301501 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1502 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301503 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301504 platform_get_snd_device_name(usecase->out_snd_device),
1505 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301506 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1507 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1508 usecase, uc_info, snd_device);
1509 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1510 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1511 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1512 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001513 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301514 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1515 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1516 ((force_restart_session) ||
1517 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301518 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1519 __func__, use_case_table[usecase->id],
1520 platform_get_snd_device_name(usecase->out_snd_device));
1521 disable_audio_route(adev, usecase);
1522 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301523 /* Enable existing usecase on derived playback device */
1524 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301525 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301526 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001527 }
1528 }
1529
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301530 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1531 num_uc_to_switch);
1532
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001533 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001534 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001535
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301536 /* Make sure the previous devices to be disabled first and then enable the
1537 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001538 list_for_each(node, &adev->usecase_list) {
1539 usecase = node_to_item(node, struct audio_usecase, list);
1540 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001541 /* Check if output sound device to be switched can be split and if any
1542 of the split devices match with derived sound device */
1543 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1544 &num_devices, split_snd_devices) == 0) {
1545 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1546 for (i = 0; i < num_devices; i++) {
1547 /* Disable devices that do not match with derived sound device */
1548 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1549 disable_snd_device(adev, split_snd_devices[i]);
1550 }
1551 } else {
1552 disable_snd_device(adev, usecase->out_snd_device);
1553 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001554 }
1555 }
1556
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001557 list_for_each(node, &adev->usecase_list) {
1558 usecase = node_to_item(node, struct audio_usecase, list);
1559 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001560 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1561 &num_devices, split_snd_devices) == 0) {
1562 /* Enable derived sound device only if it does not match with
1563 one of the split sound devices. This is because the matching
1564 sound device was not disabled */
1565 bool should_enable = true;
1566 for (i = 0; i < num_devices; i++) {
1567 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1568 should_enable = false;
1569 break;
1570 }
1571 }
1572 if (should_enable)
1573 enable_snd_device(adev, derive_snd_device[usecase->id]);
1574 } else {
1575 enable_snd_device(adev, derive_snd_device[usecase->id]);
1576 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001577 }
1578 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001579
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001580 /* Re-route all the usecases on the shared backend other than the
1581 specified usecase to new snd devices */
1582 list_for_each(node, &adev->usecase_list) {
1583 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301584 /* Update the out_snd_device only before enabling the audio route */
1585 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301586 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301587 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301588 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301589 use_case_table[usecase->id],
1590 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001591 /* Update voc calibration before enabling VoIP route */
1592 if (usecase->type == VOIP_CALL)
1593 status = platform_switch_voice_call_device_post(adev->platform,
1594 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001595 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301596 enable_audio_route(adev, usecase);
kunleiz46c47dd2018-03-19 16:28:09 +08001597 if (usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
1598 out_set_voip_volume(&usecase->stream.out->stream,
1599 usecase->stream.out->volume_l,
1600 usecase->stream.out->volume_r);
1601 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301602 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001603 }
1604 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605 }
1606}
1607
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301608static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001609 struct audio_usecase *uc_info,
1610 snd_device_t snd_device)
1611{
1612 struct listnode *node;
1613 struct audio_usecase *usecase;
1614 bool switch_device[AUDIO_USECASE_MAX];
1615 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301616 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001617 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001618
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301619 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1620 snd_device);
1621 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301622
1623 /*
1624 * Make sure out devices is checked against out codec backend device and
1625 * also in devices against in codec backend. Checking out device against in
1626 * codec backend or vice versa causes issues.
1627 */
1628 if (uc_info->type == PCM_CAPTURE)
1629 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001630 /*
1631 * This function is to make sure that all the active capture usecases
1632 * are always routed to the same input sound device.
1633 * For example, if audio-record and voice-call usecases are currently
1634 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1635 * is received for voice call then we have to make sure that audio-record
1636 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1637 * because of the limitation that two devices cannot be enabled
1638 * at the same time if they share the same backend.
1639 */
1640 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1641 switch_device[i] = false;
1642
1643 list_for_each(node, &adev->usecase_list) {
1644 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301645 /*
1646 * TODO: Enhance below condition to handle BT sco/USB multi recording
1647 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001648 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001649 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301650 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301651 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301652 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301653 (usecase->type == VOIP_CALL))) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001654 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001655 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1656 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001657 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001658 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001659 switch_device[usecase->id] = true;
1660 num_uc_to_switch++;
1661 }
1662 }
1663
1664 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001665 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001666
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301667 /* Make sure the previous devices to be disabled first and then enable the
1668 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001669 list_for_each(node, &adev->usecase_list) {
1670 usecase = node_to_item(node, struct audio_usecase, list);
1671 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001672 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001673 }
1674 }
1675
1676 list_for_each(node, &adev->usecase_list) {
1677 usecase = node_to_item(node, struct audio_usecase, list);
1678 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001679 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001680 }
1681 }
1682
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001683 /* Re-route all the usecases on the shared backend other than the
1684 specified usecase to new snd devices */
1685 list_for_each(node, &adev->usecase_list) {
1686 usecase = node_to_item(node, struct audio_usecase, list);
1687 /* Update the in_snd_device only before enabling the audio route */
1688 if (switch_device[usecase->id] ) {
1689 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001690 if (usecase->type != VOICE_CALL) {
1691 /* Update voc calibration before enabling VoIP route */
1692 if (usecase->type == VOIP_CALL)
1693 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001694 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001695 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301696 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001697 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001698 }
1699 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001700 }
1701}
1702
Mingming Yin3a941d42016-02-17 18:08:05 -08001703static void reset_hdmi_sink_caps(struct stream_out *out) {
1704 int i = 0;
1705
1706 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1707 out->supported_channel_masks[i] = 0;
1708 }
1709 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1710 out->supported_formats[i] = 0;
1711 }
1712 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1713 out->supported_sample_rates[i] = 0;
1714 }
1715}
1716
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001717/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001718static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001719{
Mingming Yin3a941d42016-02-17 18:08:05 -08001720 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001721 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001722
Mingming Yin3a941d42016-02-17 18:08:05 -08001723 reset_hdmi_sink_caps(out);
1724
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001725 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001726 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001727 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001728 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001729 }
1730
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001731 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001732 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001733 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001734 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001735 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1736 case 6:
1737 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1738 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1739 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1740 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1741 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1742 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001743 break;
1744 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001745 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001746 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747 break;
1748 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001749
1750 // check channel format caps
1751 i = 0;
1752 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1753 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1754 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1755 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1756 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1757 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1758 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1759 }
1760
Ben Romberger1aaaf862017-04-06 17:49:46 -07001761 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1762 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1763 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1764 }
1765
Mingming Yin3a941d42016-02-17 18:08:05 -08001766 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1767 ALOGV(":%s HDMI supports DTS format", __func__);
1768 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1769 }
1770
1771 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1772 ALOGV(":%s HDMI supports DTS HD format", __func__);
1773 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1774 }
1775
Naresh Tanniru928f0862017-04-07 16:44:23 -07001776 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1777 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1778 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1779 }
1780
Mingming Yin3a941d42016-02-17 18:08:05 -08001781
1782 // check sample rate caps
1783 i = 0;
1784 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1785 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1786 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1787 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1788 }
1789 }
1790
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001791 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001792}
1793
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001794static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1795 uint32_t *supported_sample_rates __unused,
1796 uint32_t max_rates __unused)
1797{
1798 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1799 supported_sample_rates,
1800 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301801 ssize_t i = 0;
1802
1803 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001804 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1805 supported_sample_rates[i]);
1806 }
1807 return count;
1808}
1809
1810static inline int read_usb_sup_channel_masks(bool is_playback,
1811 audio_channel_mask_t *supported_channel_masks,
1812 uint32_t max_masks)
1813{
1814 int channels = audio_extn_usb_get_max_channels(is_playback);
1815 int channel_count;
1816 uint32_t num_masks = 0;
1817 if (channels > MAX_HIFI_CHANNEL_COUNT)
1818 channels = MAX_HIFI_CHANNEL_COUNT;
1819
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301820 channel_count = DEFAULT_CHANNEL_COUNT;
1821
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001822 if (is_playback) {
1823 // For playback we never report mono because the framework always outputs stereo
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001824 // audio_channel_out_mask_from_count() does return positional masks for channel counts
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301825 // above 2 but we want indexed masks here.
1826 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001827 } else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001828 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1829 // indexed mask
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301830 supported_channel_masks[num_masks++] = audio_channel_in_mask_from_count(channel_count);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001831 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301832
1833 for (channel_count = channels; ((channel_count >= DEFAULT_CHANNEL_COUNT) &&
1834 (num_masks < max_masks)); channel_count--) {
1835 supported_channel_masks[num_masks++] =
1836 audio_channel_mask_for_index_assignment_from_count(channel_count);
1837 }
1838
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001839 ALOGV("%s: %s supported ch %d supported_channel_masks[0] %08x num_masks %d", __func__,
1840 is_playback ? "P" : "C", channels, supported_channel_masks[0], num_masks);
1841 return num_masks;
1842}
1843
1844static inline int read_usb_sup_formats(bool is_playback __unused,
1845 audio_format_t *supported_formats,
1846 uint32_t max_formats __unused)
1847{
1848 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1849 switch (bitwidth) {
1850 case 24:
1851 // XXX : usb.c returns 24 for s24 and s24_le?
1852 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1853 break;
1854 case 32:
1855 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1856 break;
1857 case 16:
1858 default :
1859 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1860 break;
1861 }
1862 ALOGV("%s: %s supported format %d", __func__,
1863 is_playback ? "P" : "C", bitwidth);
1864 return 1;
1865}
1866
1867static inline int read_usb_sup_params_and_compare(bool is_playback,
1868 audio_format_t *format,
1869 audio_format_t *supported_formats,
1870 uint32_t max_formats,
1871 audio_channel_mask_t *mask,
1872 audio_channel_mask_t *supported_channel_masks,
1873 uint32_t max_masks,
1874 uint32_t *rate,
1875 uint32_t *supported_sample_rates,
1876 uint32_t max_rates) {
1877 int ret = 0;
1878 int num_formats;
1879 int num_masks;
1880 int num_rates;
1881 int i;
1882
1883 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1884 max_formats);
1885 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1886 max_masks);
1887
1888 num_rates = read_usb_sup_sample_rates(is_playback,
1889 supported_sample_rates, max_rates);
1890
1891#define LUT(table, len, what, dflt) \
1892 for (i=0; i<len && (table[i] != what); i++); \
1893 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1894
1895 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1896 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1897 LUT(supported_sample_rates, num_rates, *rate, 0);
1898
1899#undef LUT
1900 return ret < 0 ? -EINVAL : 0; // HACK TBD
1901}
1902
Alexy Josephb1379942016-01-29 15:49:38 -08001903audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001904 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001905{
1906 struct audio_usecase *usecase;
1907 struct listnode *node;
1908
1909 list_for_each(node, &adev->usecase_list) {
1910 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001911 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001912 ALOGV("%s: usecase id %d", __func__, usecase->id);
1913 return usecase->id;
1914 }
1915 }
1916 return USECASE_INVALID;
1917}
1918
Alexy Josephb1379942016-01-29 15:49:38 -08001919struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001920 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001921{
1922 struct audio_usecase *usecase;
1923 struct listnode *node;
1924
1925 list_for_each(node, &adev->usecase_list) {
1926 usecase = node_to_item(node, struct audio_usecase, list);
1927 if (usecase->id == uc_id)
1928 return usecase;
1929 }
1930 return NULL;
1931}
1932
Dhananjay Kumard4833242016-10-06 22:09:12 +05301933struct stream_in *get_next_active_input(const struct audio_device *adev)
1934{
1935 struct audio_usecase *usecase;
1936 struct listnode *node;
1937
1938 list_for_each_reverse(node, &adev->usecase_list) {
1939 usecase = node_to_item(node, struct audio_usecase, list);
1940 if (usecase->type == PCM_CAPTURE)
1941 return usecase->stream.in;
1942 }
1943 return NULL;
1944}
1945
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301946/*
1947 * is a true native playback active
1948 */
1949bool audio_is_true_native_stream_active(struct audio_device *adev)
1950{
1951 bool active = false;
1952 int i = 0;
1953 struct listnode *node;
1954
1955 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1956 ALOGV("%s:napb: not in true mode or non hdphones device",
1957 __func__);
1958 active = false;
1959 goto exit;
1960 }
1961
1962 list_for_each(node, &adev->usecase_list) {
1963 struct audio_usecase *uc;
1964 uc = node_to_item(node, struct audio_usecase, list);
1965 struct stream_out *curr_out =
1966 (struct stream_out*) uc->stream.out;
1967
1968 if (curr_out && PCM_PLAYBACK == uc->type) {
1969 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
1970 "(%d) device %s", __func__, i++, use_case_table[uc->id],
1971 uc->id, curr_out->sample_rate,
1972 curr_out->bit_width,
1973 platform_get_snd_device_name(uc->out_snd_device));
1974
1975 if (is_offload_usecase(uc->id) &&
1976 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
1977 active = true;
1978 ALOGD("%s:napb:native stream detected", __func__);
1979 }
1980 }
1981 }
1982exit:
1983 return active;
1984}
1985
Xiaojun Sang785b5da2017-08-03 15:52:29 +08001986uint32_t adev_get_dsp_bit_width_enforce_mode()
1987{
1988 if (adev == NULL) {
1989 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
1990 return 0;
1991 }
1992 return adev->dsp_bit_width_enforce_mode;
1993}
1994
1995static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
1996{
1997 char value[PROPERTY_VALUE_MAX];
1998 int trial;
1999 uint32_t dsp_bit_width_enforce_mode = 0;
2000
2001 if (!mixer) {
2002 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2003 __func__);
2004 return 0;
2005 }
2006
2007 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2008 value, NULL) > 0) {
2009 trial = atoi(value);
2010 switch (trial) {
2011 case 16:
2012 dsp_bit_width_enforce_mode = 16;
2013 break;
2014 case 24:
2015 dsp_bit_width_enforce_mode = 24;
2016 break;
2017 case 32:
2018 dsp_bit_width_enforce_mode = 32;
2019 break;
2020 default:
2021 dsp_bit_width_enforce_mode = 0;
2022 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2023 break;
2024 }
2025 }
2026
2027 return dsp_bit_width_enforce_mode;
2028}
2029
2030static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2031 uint32_t enforce_mode,
2032 bool enable)
2033{
2034 struct mixer_ctl *ctl = NULL;
2035 const char *mixer_ctl_name = "ASM Bit Width";
2036 uint32_t asm_bit_width_mode = 0;
2037
2038 if (enforce_mode == 0) {
2039 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2040 return;
2041 }
2042
2043 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2044 if (!ctl) {
2045 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2046 __func__, mixer_ctl_name);
2047 return;
2048 }
2049
2050 if (enable)
2051 asm_bit_width_mode = enforce_mode;
2052 else
2053 asm_bit_width_mode = 0;
2054
2055 ALOGV("%s DSP bit width feature status is %d width=%d",
2056 __func__, enable, asm_bit_width_mode);
2057 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2058 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2059 asm_bit_width_mode);
2060
2061 return;
2062}
2063
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302064/*
2065 * if native DSD playback active
2066 */
2067bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2068{
2069 bool active = false;
2070 struct listnode *node = NULL;
2071 struct audio_usecase *uc = NULL;
2072 struct stream_out *curr_out = NULL;
2073
2074 list_for_each(node, &adev->usecase_list) {
2075 uc = node_to_item(node, struct audio_usecase, list);
2076 curr_out = (struct stream_out*) uc->stream.out;
2077
2078 if (curr_out && PCM_PLAYBACK == uc->type &&
2079 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2080 active = true;
2081 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302082 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302083 }
2084 }
2085 return active;
2086}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302087
2088static bool force_device_switch(struct audio_usecase *usecase)
2089{
2090 bool ret = false;
2091 bool is_it_true_mode = false;
2092
Zhou Song30f2c3e2018-02-08 14:02:15 +08002093 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302094 usecase->type == TRANSCODE_LOOPBACK_RX ||
2095 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002096 return false;
2097 }
2098
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002099 if(usecase->stream.out == NULL) {
2100 ALOGE("%s: stream.out is NULL", __func__);
2101 return false;
2102 }
2103
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302104 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002105 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2106 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2107 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302108 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2109 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2110 (!is_it_true_mode && adev->native_playback_enabled)){
2111 ret = true;
2112 ALOGD("napb: time to toggle native mode");
2113 }
2114 }
2115
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302116 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302117 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2118 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002119 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302120 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302121 ALOGD("Force a2dp device switch to update new encoder config");
2122 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002123 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302124
Florian Pfister1a84f312018-07-19 14:38:18 +02002125 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302126 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2127 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002128 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302129 return ret;
2130}
2131
Aalique Grahame22e49102018-12-18 14:23:57 -08002132static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2133{
2134 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2135}
2136
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302137bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2138{
2139 bool ret=false;
2140 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2141 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2142 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2143 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2144 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2145 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2146 ret = true;
2147
2148 return ret;
2149}
2150
2151bool is_a2dp_device(snd_device_t out_snd_device)
2152{
2153 bool ret=false;
2154 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2155 ret = true;
2156
2157 return ret;
2158}
2159
2160bool is_bt_soc_on(struct audio_device *adev)
2161{
2162 struct mixer_ctl *ctl;
2163 char *mixer_ctl_name = "BT SOC status";
2164 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2165 bool bt_soc_status = true;
2166 if (!ctl) {
2167 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2168 __func__, mixer_ctl_name);
2169 /*This is to ensure we dont break targets which dont have the kernel change*/
2170 return true;
2171 }
2172 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2173 ALOGD("BT SOC status: %d",bt_soc_status);
2174 return bt_soc_status;
2175}
2176
2177int out_standby_l(struct audio_stream *stream);
2178
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002179int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002180{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002181 snd_device_t out_snd_device = SND_DEVICE_NONE;
2182 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002183 struct audio_usecase *usecase = NULL;
2184 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002185 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002186 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302187 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002188 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002189 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002190
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302191 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2192
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002193 usecase = get_usecase_from_list(adev, uc_id);
2194 if (usecase == NULL) {
2195 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2196 return -EINVAL;
2197 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002198
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002199 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002200 (usecase->type == VOIP_CALL) ||
2201 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302202 if(usecase->stream.out == NULL) {
2203 ALOGE("%s: stream.out is NULL", __func__);
2204 return -EINVAL;
2205 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002206 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002207 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002208 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002209 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302210 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302211 if (usecase->stream.inout == NULL) {
2212 ALOGE("%s: stream.inout is NULL", __func__);
2213 return -EINVAL;
2214 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302215 stream_out.devices = usecase->stream.inout->out_config.devices;
2216 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2217 stream_out.format = usecase->stream.inout->out_config.format;
2218 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2219 out_snd_device = platform_get_output_snd_device(adev->platform,
2220 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302221 usecase->devices = out_snd_device;
2222 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2223 if (usecase->stream.inout == NULL) {
2224 ALOGE("%s: stream.inout is NULL", __func__);
2225 return -EINVAL;
2226 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302227 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302228 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002229 } else {
2230 /*
2231 * If the voice call is active, use the sound devices of voice call usecase
2232 * so that it would not result any device switch. All the usecases will
2233 * be switched to new device when select_devices() is called for voice call
2234 * usecase. This is to avoid switching devices for voice call when
2235 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002236 * choose voice call device only if the use case device is
2237 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002238 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002239 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002240 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002241 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002242 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2243 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302244 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2245 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
Alexy Josephdbcddf22016-05-16 17:54:09 -07002246 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002247 in_snd_device = vc_usecase->in_snd_device;
2248 out_snd_device = vc_usecase->out_snd_device;
2249 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002250 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002251 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002252 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002253 if ((voip_usecase != NULL) &&
2254 (usecase->type == PCM_PLAYBACK) &&
2255 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002256 out_snd_device_backend_match = platform_check_backends_match(
2257 voip_usecase->out_snd_device,
2258 platform_get_output_snd_device(
2259 adev->platform,
2260 usecase->stream.out));
2261 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002262 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002263 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2264 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002265 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002266 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002267 in_snd_device = voip_usecase->in_snd_device;
2268 out_snd_device = voip_usecase->out_snd_device;
2269 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002270 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002271 hfp_ucid = audio_extn_hfp_get_usecase();
2272 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002273 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002274 in_snd_device = hfp_usecase->in_snd_device;
2275 out_snd_device = hfp_usecase->out_snd_device;
2276 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002277 }
2278 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302279 if (usecase->stream.out == NULL) {
2280 ALOGE("%s: stream.out is NULL", __func__);
2281 return -EINVAL;
2282 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002283 usecase->devices = usecase->stream.out->devices;
2284 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002285 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002286 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002287 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002288 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002289 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002290 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2291
2292 if ((usecase->stream.out != NULL &&
2293 voip_usecase != NULL &&
2294 usecase->stream.out->usecase == voip_usecase->id) &&
2295 adev->active_input &&
Aalique Grahame22e49102018-12-18 14:23:57 -08002296 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2297 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
kunleizdcf967a2018-08-07 17:09:11 +08002298 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002299 select_devices(adev, adev->active_input->usecase);
2300 }
2301 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002302 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302303 if (usecase->stream.in == NULL) {
2304 ALOGE("%s: stream.in is NULL", __func__);
2305 return -EINVAL;
2306 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002307 usecase->devices = usecase->stream.in->device;
2308 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002309 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002310 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002311 if (adev->active_input &&
2312 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302313 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002314 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2315 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2316 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2317 out_device = voip_usecase->stream.out->devices;
2318 else if (adev->primary_output && !adev->primary_output->standby)
2319 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002320 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002321 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2322 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002323 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002324 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002325 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002326 }
2327 }
2328
2329 if (out_snd_device == usecase->out_snd_device &&
2330 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302331
2332 if (!force_device_switch(usecase))
2333 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002334 }
2335
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302336 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002337 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302338 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2339 return 0;
2340 }
2341
Aalique Grahame22e49102018-12-18 14:23:57 -08002342 if (out_snd_device != SND_DEVICE_NONE &&
2343 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2344 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2345 __func__,
2346 use_case_table[uc_id],
2347 adev->last_logged_snd_device[uc_id][0],
2348 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2349 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2350 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2351 -1,
2352 out_snd_device,
2353 platform_get_snd_device_name(out_snd_device),
2354 platform_get_snd_device_acdb_id(out_snd_device));
2355 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2356 }
2357 if (in_snd_device != SND_DEVICE_NONE &&
2358 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2359 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2360 __func__,
2361 use_case_table[uc_id],
2362 adev->last_logged_snd_device[uc_id][1],
2363 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2364 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2365 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2366 -1,
2367 in_snd_device,
2368 platform_get_snd_device_name(in_snd_device),
2369 platform_get_snd_device_acdb_id(in_snd_device));
2370 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2371 }
2372
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002374 /*
2375 * Limitation: While in call, to do a device switch we need to disable
2376 * and enable both RX and TX devices though one of them is same as current
2377 * device.
2378 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002379 if ((usecase->type == VOICE_CALL) &&
2380 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2381 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002382 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002383 }
2384
2385 if (((usecase->type == VOICE_CALL) ||
2386 (usecase->type == VOIP_CALL)) &&
2387 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2388 /* Disable sidetone only if voice/voip call already exists */
2389 if (voice_is_call_state_active(adev) ||
2390 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002391 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002392
2393 /* Disable aanc only if voice call exists */
2394 if (voice_is_call_state_active(adev))
2395 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002396 }
2397
Aalique Grahame22e49102018-12-18 14:23:57 -08002398 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2399 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002400 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302401 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002402 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2403 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2404 else
2405 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302406 }
2407
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002408 /* Disable current sound devices */
2409 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002410 disable_audio_route(adev, usecase);
2411 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002412 }
2413
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002414 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002415 disable_audio_route(adev, usecase);
2416 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002417 }
2418
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002419 /* Applicable only on the targets that has external modem.
2420 * New device information should be sent to modem before enabling
2421 * the devices to reduce in-call device switch time.
2422 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002423 if ((usecase->type == VOICE_CALL) &&
2424 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2425 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002426 status = platform_switch_voice_call_enable_device_config(adev->platform,
2427 out_snd_device,
2428 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002429 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002430
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002431 /* Enable new sound devices */
2432 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002433 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302434 if (platform_check_codec_asrc_support(adev->platform))
2435 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002436 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002437 }
2438
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002439 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302440 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002441 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002442 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002443
Avinash Vaish71a8b972014-07-24 15:36:33 +05302444 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002445 status = platform_switch_voice_call_device_post(adev->platform,
2446 out_snd_device,
2447 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302448 enable_audio_route_for_voice_usecases(adev, usecase);
2449 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002450
sangwoo170731f2013-06-08 15:36:36 +09002451 usecase->in_snd_device = in_snd_device;
2452 usecase->out_snd_device = out_snd_device;
2453
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302454 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2455 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302456 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002457 if ((24 == usecase->stream.out->bit_width) &&
2458 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2459 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2460 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2461 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2462 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2463 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2464 /*
2465 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2466 * configured device sample rate, if not update the COPP rate to be equal to the
2467 * device sample rate, else open COPP at stream sample rate
2468 */
2469 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2470 usecase->stream.out->sample_rate,
2471 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302472 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2473 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002474 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2475 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2476 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2477 }
2478
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002479 /* Notify device change info to effect clients registered */
2480 audio_extn_gef_notify_device_config(
2481 usecase->stream.out->devices,
2482 usecase->stream.out->channel_mask,
2483 usecase->stream.out->app_type_cfg.sample_rate,
2484 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302485 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002486 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002487
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002488 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002489
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002490 /* If input stream is already running then effect needs to be
2491 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002492 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2493 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002494 check_and_enable_effect(adev);
2495
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002496 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002497 /* Enable aanc only if voice call exists */
2498 if (voice_is_call_state_active(adev))
2499 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2500
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002501 /* Enable sidetone only if other voice/voip call already exists */
2502 if (voice_is_call_state_active(adev) ||
2503 voice_extn_compress_voip_is_started(adev))
2504 voice_set_sidetone(adev, out_snd_device, true);
2505 }
2506
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002507 /* Applicable only on the targets that has external modem.
2508 * Enable device command should be sent to modem only after
2509 * enabling voice call mixer controls
2510 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002511 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002512 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2513 out_snd_device,
2514 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302515
2516 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2517
2518 if (usecase->type == VOIP_CALL) {
2519 if (adev->active_input != NULL &&
2520 !adev->active_input->standby) {
2521 if (is_bt_soc_on(adev) == false){
2522 ALOGD("BT SCO MIC disconnected while in connection");
2523 if (adev->active_input->pcm != NULL)
2524 pcm_stop(adev->active_input->pcm);
2525 }
2526 }
2527 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2528 && usecase->stream.out->started) {
2529 if (is_bt_soc_on(adev) == false) {
2530 ALOGD("BT SCO/A2DP disconnected while in connection");
2531 out_standby_l(&usecase->stream.out->stream.common);
2532 }
2533 }
2534 } else if ((usecase->stream.out != NULL) &&
2535 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302536 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2537 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302538 usecase->stream.out->started) {
2539 if (is_bt_soc_on(adev) == false) {
2540 ALOGD("BT SCO/A2dp disconnected while in connection");
2541 out_standby_l(&usecase->stream.out->stream.common);
2542 }
2543 }
2544 }
2545
Aalique Grahame22e49102018-12-18 14:23:57 -08002546 if (usecase == voip_usecase) {
2547 struct stream_out *voip_out = voip_usecase->stream.out;
2548 audio_extn_utils_send_app_type_gain(adev,
2549 voip_out->app_type_cfg.app_type,
2550 &voip_out->app_type_cfg.gain[0]);
2551 }
2552
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302553 ALOGD("%s: done",__func__);
2554
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002555 return status;
2556}
2557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002558static int stop_input_stream(struct stream_in *in)
2559{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302560 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002561 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302562
2563 if (in == NULL) {
2564 ALOGE("%s: stream_in ptr is NULL", __func__);
2565 return -EINVAL;
2566 }
2567
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002568 struct audio_device *adev = in->dev;
2569
Eric Laurent994a6932013-07-17 11:51:42 -07002570 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002571 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002572 uc_info = get_usecase_from_list(adev, in->usecase);
2573 if (uc_info == NULL) {
2574 ALOGE("%s: Could not find the usecase (%d) in the list",
2575 __func__, in->usecase);
2576 return -EINVAL;
2577 }
2578
Derek Chenea197282019-01-07 17:35:01 -08002579 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2580 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002581
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002582 /* Close in-call recording streams */
2583 voice_check_and_stop_incall_rec_usecase(adev, in);
2584
Eric Laurent150dbfe2013-02-27 14:31:02 -08002585 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002586 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002587
2588 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002589 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002590
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002591 list_remove(&uc_info->list);
2592 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002593
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002594 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302595 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002596 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002597 return ret;
2598}
2599
2600int start_input_stream(struct stream_in *in)
2601{
2602 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002603 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002604 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302605
2606 if (in == NULL) {
2607 ALOGE("%s: stream_in ptr is NULL", __func__);
2608 return -EINVAL;
2609 }
2610
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002611 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002612 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002613 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002614
Mingming Yin2664a5b2015-09-03 10:53:11 -07002615 if (get_usecase_from_list(adev, usecase) == NULL)
2616 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302617 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2618 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002619
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302620 if (CARD_STATUS_OFFLINE == in->card_status||
2621 CARD_STATUS_OFFLINE == adev->card_status) {
2622 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302623 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302624 goto error_config;
2625 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302626
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302627 if (audio_is_bluetooth_sco_device(in->device)) {
2628 if (!adev->bt_sco_on) {
2629 ALOGE("%s: SCO profile is not ready, return error", __func__);
2630 ret = -EIO;
2631 goto error_config;
2632 }
2633 }
2634
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002635 /* Check if source matches incall recording usecase criteria */
2636 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2637 if (ret)
2638 goto error_config;
2639 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002640 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2641
2642 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2643 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2644 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002645 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002646 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002647
Eric Laurentb23d5282013-05-14 15:27:20 -07002648 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002649 if (in->pcm_device_id < 0) {
2650 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2651 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002652 ret = -EINVAL;
2653 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002654 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002655
2656 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002657 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002658
2659 if (!uc_info) {
2660 ret = -ENOMEM;
2661 goto error_config;
2662 }
2663
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002664 uc_info->id = in->usecase;
2665 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002666 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002667 uc_info->devices = in->device;
2668 uc_info->in_snd_device = SND_DEVICE_NONE;
2669 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002670
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002671 list_add_tail(&adev->usecase_list, &uc_info->list);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302672 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2673 adev->perf_lock_opts,
2674 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002675 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002676
Derek Chenea197282019-01-07 17:35:01 -08002677 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2678 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002679
Haynes Mathew George16081042017-05-31 17:16:49 -07002680 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302681 ret = audio_extn_cin_start_input_stream(in);
2682 if (ret)
2683 goto error_open;
2684 else
2685 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002686 }
2687
Haynes Mathew George16081042017-05-31 17:16:49 -07002688 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002689 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002690 ALOGE("%s: pcm stream not ready", __func__);
2691 goto error_open;
2692 }
2693 ret = pcm_start(in->pcm);
2694 if (ret < 0) {
2695 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2696 goto error_open;
2697 }
2698 } else {
2699 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2700 unsigned int pcm_open_retry_count = 0;
2701
2702 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2703 flags |= PCM_MMAP | PCM_NOIRQ;
2704 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2705 } else if (in->realtime) {
2706 flags |= PCM_MMAP | PCM_NOIRQ;
2707 }
2708
Garmond Leunge2433c32017-09-28 21:51:22 -07002709 if (audio_extn_ffv_get_stream() == in) {
2710 ALOGD("%s: ffv stream, update pcm config", __func__);
2711 audio_extn_ffv_update_pcm_config(&config);
2712 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002713 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2714 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2715
2716 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002717 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002718 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002719 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002720 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302721 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302722 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2723 adev->card_status = CARD_STATUS_OFFLINE;
2724 in->card_status = CARD_STATUS_OFFLINE;
2725 ret = -EIO;
2726 goto error_open;
2727 }
2728
Haynes Mathew George16081042017-05-31 17:16:49 -07002729 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2730 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2731 if (in->pcm != NULL) {
2732 pcm_close(in->pcm);
2733 in->pcm = NULL;
2734 }
2735 if (pcm_open_retry_count-- == 0) {
2736 ret = -EIO;
2737 goto error_open;
2738 }
2739 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2740 continue;
2741 }
2742 break;
2743 }
2744
2745 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002746 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002747 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002748 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002749 if (ret < 0) {
2750 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2751 pcm_close(in->pcm);
2752 in->pcm = NULL;
2753 goto error_open;
2754 }
2755 register_in_stream(in);
2756 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002757 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002758 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002759 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002760 if (ret < 0) {
2761 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002762 pcm_close(in->pcm);
2763 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002764 goto error_open;
2765 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002766 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002767 }
2768
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002769 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07002770 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
2771 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002772
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302773done_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302774 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002775 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302776 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002777 return ret;
2778
2779error_open:
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302780 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002781 stop_input_stream(in);
Eric Laurentc8400632013-02-14 19:04:54 -08002782error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302783 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302784 /*
2785 * sleep 50ms to allow sufficient time for kernel
2786 * drivers to recover incases like SSR.
2787 */
2788 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002789 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302790 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002791 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002792}
2793
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002794void lock_input_stream(struct stream_in *in)
2795{
2796 pthread_mutex_lock(&in->pre_lock);
2797 pthread_mutex_lock(&in->lock);
2798 pthread_mutex_unlock(&in->pre_lock);
2799}
2800
2801void lock_output_stream(struct stream_out *out)
2802{
2803 pthread_mutex_lock(&out->pre_lock);
2804 pthread_mutex_lock(&out->lock);
2805 pthread_mutex_unlock(&out->pre_lock);
2806}
2807
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002808/* must be called with out->lock locked */
2809static int send_offload_cmd_l(struct stream_out* out, int command)
2810{
2811 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2812
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002813 if (!cmd) {
2814 ALOGE("failed to allocate mem for command 0x%x", command);
2815 return -ENOMEM;
2816 }
2817
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002818 ALOGVV("%s %d", __func__, command);
2819
2820 cmd->cmd = command;
2821 list_add_tail(&out->offload_cmd_list, &cmd->node);
2822 pthread_cond_signal(&out->offload_cond);
2823 return 0;
2824}
2825
2826/* must be called iwth out->lock locked */
2827static void stop_compressed_output_l(struct stream_out *out)
2828{
2829 out->offload_state = OFFLOAD_STATE_IDLE;
2830 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002831 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002832 if (out->compr != NULL) {
2833 compress_stop(out->compr);
2834 while (out->offload_thread_blocked) {
2835 pthread_cond_wait(&out->cond, &out->lock);
2836 }
2837 }
2838}
2839
Varun Balaraje49253e2017-07-06 19:48:56 +05302840bool is_interactive_usecase(audio_usecase_t uc_id)
2841{
2842 unsigned int i;
2843 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2844 if (uc_id == interactive_usecases[i])
2845 return true;
2846 }
2847 return false;
2848}
2849
2850static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2851{
2852 audio_usecase_t ret_uc = USECASE_INVALID;
2853 unsigned int intract_uc_index;
2854 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2855
2856 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2857 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2858 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2859 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2860 ret_uc = interactive_usecases[intract_uc_index];
2861 break;
2862 }
2863 }
2864
2865 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2866 return ret_uc;
2867}
2868
2869static void free_interactive_usecase(struct audio_device *adev,
2870 audio_usecase_t uc_id)
2871{
2872 unsigned int interact_uc_index;
2873 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2874
2875 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2876 if (interactive_usecases[interact_uc_index] == uc_id) {
2877 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2878 break;
2879 }
2880 }
2881 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2882}
2883
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002884bool is_offload_usecase(audio_usecase_t uc_id)
2885{
2886 unsigned int i;
2887 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2888 if (uc_id == offload_usecases[i])
2889 return true;
2890 }
2891 return false;
2892}
2893
Dhananjay Kumarac341582017-02-23 23:42:25 +05302894static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002895{
vivek mehta446c3962015-09-14 10:57:35 -07002896 audio_usecase_t ret_uc = USECASE_INVALID;
2897 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002898 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002899 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302900 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002901 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2902 else
2903 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002904
vivek mehta446c3962015-09-14 10:57:35 -07002905 pthread_mutex_lock(&adev->lock);
2906 if (get_usecase_from_list(adev, ret_uc) != NULL)
2907 ret_uc = USECASE_INVALID;
2908 pthread_mutex_unlock(&adev->lock);
2909
2910 return ret_uc;
2911 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002912
2913 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002914 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2915 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2916 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2917 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002918 break;
2919 }
2920 }
vivek mehta446c3962015-09-14 10:57:35 -07002921
2922 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2923 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002924}
2925
2926static void free_offload_usecase(struct audio_device *adev,
2927 audio_usecase_t uc_id)
2928{
vivek mehta446c3962015-09-14 10:57:35 -07002929 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002930 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002931
2932 if (!adev->multi_offload_enable)
2933 return;
2934
2935 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2936 if (offload_usecases[offload_uc_index] == uc_id) {
2937 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002938 break;
2939 }
2940 }
2941 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2942}
2943
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002944static void *offload_thread_loop(void *context)
2945{
2946 struct stream_out *out = (struct stream_out *) context;
2947 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08002948 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002949
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002950 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002951 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002952 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
2953
2954 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002955 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002956 for (;;) {
2957 struct offload_cmd *cmd = NULL;
2958 stream_callback_event_t event;
2959 bool send_callback = false;
2960
2961 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
2962 __func__, list_empty(&out->offload_cmd_list),
2963 out->offload_state);
2964 if (list_empty(&out->offload_cmd_list)) {
2965 ALOGV("%s SLEEPING", __func__);
2966 pthread_cond_wait(&out->offload_cond, &out->lock);
2967 ALOGV("%s RUNNING", __func__);
2968 continue;
2969 }
2970
2971 item = list_head(&out->offload_cmd_list);
2972 cmd = node_to_item(item, struct offload_cmd, node);
2973 list_remove(item);
2974
2975 ALOGVV("%s STATE %d CMD %d out->compr %p",
2976 __func__, out->offload_state, cmd->cmd, out->compr);
2977
2978 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
2979 free(cmd);
2980 break;
2981 }
2982
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08002983 // allow OFFLOAD_CMD_ERROR reporting during standby
2984 // this is needed to handle failures during compress_open
2985 // Note however that on a pause timeout, the stream is closed
2986 // and no offload usecase will be active. Therefore this
2987 // special case is needed for compress_open failures alone
2988 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
2989 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002990 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07002991 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002992 pthread_cond_signal(&out->cond);
2993 continue;
2994 }
2995 out->offload_thread_blocked = true;
2996 pthread_mutex_unlock(&out->lock);
2997 send_callback = false;
2998 switch(cmd->cmd) {
2999 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003000 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003001 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003002 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003003 send_callback = true;
3004 event = STREAM_CBK_EVENT_WRITE_READY;
3005 break;
3006 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003007 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303008 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003009 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303010 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003011 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303012 if (ret < 0)
3013 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303014 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303015 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003016 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003017 else
3018 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003019 if (-ENETRESET != ret && !(-EINTR == ret &&
3020 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303021 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303022 pthread_mutex_lock(&out->lock);
3023 out->send_new_metadata = 1;
3024 out->send_next_track_params = true;
3025 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303026 event = STREAM_CBK_EVENT_DRAIN_READY;
3027 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3028 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303029 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003030 break;
3031 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003032 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003033 ret = compress_drain(out->compr);
3034 ALOGD("copl(%p):out of compress_drain", out);
3035 // EINTR check avoids drain interruption due to SSR
3036 if (-ENETRESET != ret && !(-EINTR == ret &&
3037 CARD_STATUS_OFFLINE == out->card_status)) {
3038 send_callback = true;
3039 event = STREAM_CBK_EVENT_DRAIN_READY;
3040 } else
3041 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003042 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303043 case OFFLOAD_CMD_ERROR:
3044 ALOGD("copl(%p): sending error callback to AF", out);
3045 send_callback = true;
3046 event = STREAM_CBK_EVENT_ERROR;
3047 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003048 default:
3049 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3050 break;
3051 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003052 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003053 out->offload_thread_blocked = false;
3054 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003055 if (send_callback && out->client_callback) {
3056 ALOGVV("%s: sending client_callback event %d", __func__, event);
3057 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003058 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003059 free(cmd);
3060 }
3061
3062 pthread_cond_signal(&out->cond);
3063 while (!list_empty(&out->offload_cmd_list)) {
3064 item = list_head(&out->offload_cmd_list);
3065 list_remove(item);
3066 free(node_to_item(item, struct offload_cmd, node));
3067 }
3068 pthread_mutex_unlock(&out->lock);
3069
3070 return NULL;
3071}
3072
3073static int create_offload_callback_thread(struct stream_out *out)
3074{
3075 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3076 list_init(&out->offload_cmd_list);
3077 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3078 offload_thread_loop, out);
3079 return 0;
3080}
3081
3082static int destroy_offload_callback_thread(struct stream_out *out)
3083{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003084 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003085 stop_compressed_output_l(out);
3086 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3087
3088 pthread_mutex_unlock(&out->lock);
3089 pthread_join(out->offload_thread, (void **) NULL);
3090 pthread_cond_destroy(&out->offload_cond);
3091
3092 return 0;
3093}
3094
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003095static int stop_output_stream(struct stream_out *out)
3096{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303097 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003098 struct audio_usecase *uc_info;
3099 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003100 bool has_voip_usecase =
3101 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003102
Eric Laurent994a6932013-07-17 11:51:42 -07003103 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003104 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003105 uc_info = get_usecase_from_list(adev, out->usecase);
3106 if (uc_info == NULL) {
3107 ALOGE("%s: Could not find the usecase (%d) in the list",
3108 __func__, out->usecase);
3109 return -EINVAL;
3110 }
3111
Derek Chenea197282019-01-07 17:35:01 -08003112 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3113 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003114
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003115 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303116 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003117 if (adev->visualizer_stop_output != NULL)
3118 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003119
3120 audio_extn_dts_remove_state_notifier_node(out->usecase);
3121
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003122 if (adev->offload_effects_stop_output != NULL)
3123 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
3124 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003125
Arun Mirpurief53ce52018-09-11 18:00:09 -07003126 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3127 voice_set_device_mute_flag(adev, false);
3128
Eric Laurent150dbfe2013-02-27 14:31:02 -08003129 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003130 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003131
3132 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003133 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003134
Aalique Grahame22e49102018-12-18 14:23:57 -08003135 audio_extn_extspk_update(adev->extspk);
3136
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003137 if (is_offload_usecase(out->usecase)) {
3138 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3139 adev->dsp_bit_width_enforce_mode,
3140 false);
3141 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003142 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3143 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3144 false);
3145
3146 if (ret != 0)
3147 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3148 /* default service interval was successfully updated,
3149 reopen USB backend with new service interval */
3150 ret = 0;
3151 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003152
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003153 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303154 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003155 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303156 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003157 ALOGV("Disable passthrough , reset mixer to pcm");
3158 /* NO_PASSTHROUGH */
3159 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003160 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003161 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3162 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003163
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303164 /* Must be called after removing the usecase from list */
3165 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303166 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303167
Manish Dewangan21a850a2017-08-14 12:03:55 +05303168 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003169 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3170 if (ret < 0)
3171 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3172 }
3173
Aalique Grahame22e49102018-12-18 14:23:57 -08003174 if (has_voip_usecase ||
3175 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3176 struct listnode *node;
3177 struct audio_usecase *usecase;
3178 list_for_each(node, &adev->usecase_list) {
3179 usecase = node_to_item(node, struct audio_usecase, list);
3180 if (usecase->type == PCM_CAPTURE || usecase == uc_info)
3181 continue;
3182
3183 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3184 __func__, usecase->id, use_case_table[usecase->id],
3185 out->usecase, use_case_table[out->usecase]);
3186 select_devices(adev, usecase->id);
3187 }
3188 }
3189
Garmond Leung5fd0b552018-04-17 11:56:12 -07003190 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003191 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003192 return ret;
3193}
3194
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003195struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3196 unsigned int flags, unsigned int pcm_open_retry_count,
3197 struct pcm_config *config)
3198{
3199 struct pcm* pcm = NULL;
3200
3201 while (1) {
3202 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3203 if (pcm == NULL || !pcm_is_ready(pcm)) {
3204 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3205 if (pcm != NULL) {
3206 pcm_close(pcm);
3207 pcm = NULL;
3208 }
3209 if (pcm_open_retry_count-- == 0)
3210 return NULL;
3211
3212 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3213 continue;
3214 }
3215 break;
3216 }
3217
3218 if (pcm_is_ready(pcm)) {
3219 int ret = pcm_prepare(pcm);
3220 if (ret < 0) {
3221 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3222 pcm_close(pcm);
3223 pcm = NULL;
3224 }
3225 }
3226
3227 return pcm;
3228}
3229
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003230int start_output_stream(struct stream_out *out)
3231{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003232 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003233 struct audio_usecase *uc_info;
3234 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003235 char mixer_ctl_name[128];
3236 struct mixer_ctl *ctl = NULL;
3237 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303238 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003239 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003240
Haynes Mathew George380745d2017-10-04 15:27:45 -07003241 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003242 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3243 ret = -EINVAL;
3244 goto error_config;
3245 }
3246
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003247 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303248 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003249 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303250
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303251 if (CARD_STATUS_OFFLINE == out->card_status ||
3252 CARD_STATUS_OFFLINE == adev->card_status) {
3253 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303254 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303255 goto error_config;
3256 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303257
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303258 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003259 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003260 if (out->devices &
3261 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303262 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303263 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303264 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3265 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3266 ret = -EAGAIN;
3267 goto error_config;
3268 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303269 }
3270 }
3271 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303272 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3273 if (!adev->bt_sco_on) {
3274 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3275 //combo usecase just by pass a2dp
3276 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3277 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3278 } else {
3279 ALOGE("%s: SCO profile is not ready, return error", __func__);
3280 ret = -EAGAIN;
3281 goto error_config;
3282 }
3283 }
3284 }
3285
Eric Laurentb23d5282013-05-14 15:27:20 -07003286 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003287 if (out->pcm_device_id < 0) {
3288 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3289 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003290 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003291 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003292 }
3293
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003294 if (is_haptic_usecase) {
3295 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3296 if (adev->haptic_pcm_device_id < 0) {
3297 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3298 __func__, adev->haptic_pcm_device_id, out->usecase);
3299 ret = -EINVAL;
3300 goto error_config;
3301 }
3302 }
3303
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003304 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003305
3306 if (!uc_info) {
3307 ret = -ENOMEM;
3308 goto error_config;
3309 }
3310
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003311 uc_info->id = out->usecase;
3312 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003313 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003314 uc_info->devices = out->devices;
3315 uc_info->in_snd_device = SND_DEVICE_NONE;
3316 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003317
3318 /* This must be called before adding this usecase to the list */
3319 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3320 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3321 /* USB backend is not reopened immediately.
3322 This is eventually done as part of select_devices */
3323 }
3324
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003325 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003326
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303327 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3328 adev->perf_lock_opts,
3329 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303330
3331 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303332 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303333 if (audio_extn_passthru_is_enabled() &&
3334 audio_extn_passthru_is_passthrough_stream(out)) {
3335 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303336 }
3337 }
3338
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303339 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003340 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303341 if (!a2dp_combo) {
3342 check_a2dp_restore_l(adev, out, false);
3343 } else {
3344 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003345 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3346 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3347 else
3348 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303349 select_devices(adev, out->usecase);
3350 out->devices = dev;
3351 }
3352 } else {
3353 select_devices(adev, out->usecase);
3354 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003355
Arun Mirpurief53ce52018-09-11 18:00:09 -07003356 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3357 voice_set_device_mute_flag(adev, true);
3358
Derek Chenea197282019-01-07 17:35:01 -08003359 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3360 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003361
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003362 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3363 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003364
3365 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003366 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003367 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3368 ALOGE("%s: pcm stream not ready", __func__);
3369 goto error_open;
3370 }
3371 ret = pcm_start(out->pcm);
3372 if (ret < 0) {
3373 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3374 goto error_open;
3375 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003376 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003377 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003378 unsigned int flags = PCM_OUT;
3379 unsigned int pcm_open_retry_count = 0;
3380 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3381 flags |= PCM_MMAP | PCM_NOIRQ;
3382 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003383 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003384 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003385 } else
3386 flags |= PCM_MONOTONIC;
3387
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003388 if ((adev->vr_audio_mode_enabled) &&
3389 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3390 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3391 "PCM_Dev %d Topology", out->pcm_device_id);
3392 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3393 if (!ctl) {
3394 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3395 __func__, mixer_ctl_name);
3396 } else {
3397 //if success use ULLPP
3398 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3399 __func__, mixer_ctl_name, out->pcm_device_id);
3400 //There is a still a possibility that some sessions
3401 // that request for FAST|RAW when 3D audio is active
3402 //can go through ULLPP. Ideally we expects apps to
3403 //listen to audio focus and stop concurrent playback
3404 //Also, we will look for mode flag (voice_in_communication)
3405 //before enabling the realtime flag.
3406 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3407 }
3408 }
3409
Surendar Karka91fa3682018-07-02 18:12:12 +05303410 if (out->realtime)
3411 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3412 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3413
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003414 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3415 flags, pcm_open_retry_count,
3416 &(out->config));
3417 if (out->pcm == NULL) {
3418 ret = -EIO;
3419 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003420 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003421
3422 if (is_haptic_usecase) {
3423 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3424 adev->haptic_pcm_device_id,
3425 flags, pcm_open_retry_count,
3426 &(adev->haptics_config));
3427 // failure to open haptics pcm shouldnt stop audio,
3428 // so do not close audio pcm in case of error
3429 }
3430
Surendar Karka91fa3682018-07-02 18:12:12 +05303431 if (!out->realtime)
3432 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303433 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003434
Zhou Song2b8f28f2017-09-11 10:51:38 +08003435 // apply volume for voip playback after path is set up
3436 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3437 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303438 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3439 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303440 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3441 out->apply_volume = false;
3442 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003443 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003444 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303445 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003446 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3447 adev->dsp_bit_width_enforce_mode,
3448 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003449 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003450 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003451 out->compr = compress_open(adev->snd_card,
3452 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003453 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003454 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303455 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303456 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3457 adev->card_status = CARD_STATUS_OFFLINE;
3458 out->card_status = CARD_STATUS_OFFLINE;
3459 ret = -EIO;
3460 goto error_open;
3461 }
3462
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003463 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003464 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003465 compress_close(out->compr);
3466 out->compr = NULL;
3467 ret = -EIO;
3468 goto error_open;
3469 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303470 /* compress_open sends params of the track, so reset the flag here */
3471 out->is_compr_metadata_avail = false;
3472
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003473 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003474 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003475
Fred Oh3f43e742015-03-04 18:42:34 -08003476 /* Since small bufs uses blocking writes, a write will be blocked
3477 for the default max poll time (20s) in the event of an SSR.
3478 Reduce the poll time to observe and deal with SSR faster.
3479 */
Ashish Jain5106d362016-05-11 19:23:33 +05303480 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003481 compress_set_max_poll_wait(out->compr, 1000);
3482 }
3483
Manish Dewangan69426c82017-01-30 17:35:36 +05303484 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303485 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303486
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003487 audio_extn_dts_create_state_notifier_node(out->usecase);
3488 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3489 popcount(out->channel_mask),
3490 out->playback_started);
3491
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003492#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303493 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003494 audio_extn_dolby_send_ddp_endp_params(adev);
3495#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303496 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3497 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003498 if (adev->visualizer_start_output != NULL)
3499 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3500 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303501 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003502 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003503 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003504 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003505
3506 if (ret == 0) {
3507 register_out_stream(out);
3508 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003509 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3510 ALOGE("%s: pcm stream not ready", __func__);
3511 goto error_open;
3512 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003513 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003514 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003515 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003516 if (ret < 0)
3517 goto error_open;
3518 }
3519 }
3520
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303521 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003522 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003523
Manish Dewangan21a850a2017-08-14 12:03:55 +05303524 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003525 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003526 if (ret < 0)
3527 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3528 }
3529
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003530 // consider a scenario where on pause lower layers are tear down.
3531 // so on resume, swap mixer control need to be sent only when
3532 // backend is active, hence rather than sending from enable device
3533 // sending it from start of streamtream
3534
3535 platform_set_swap_channels(adev, true);
3536
Haynes Mathew George380745d2017-10-04 15:27:45 -07003537 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303538 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003539 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003540error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003541 if (adev->haptic_pcm) {
3542 pcm_close(adev->haptic_pcm);
3543 adev->haptic_pcm = NULL;
3544 }
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303545 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003546 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003547error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303548 /*
3549 * sleep 50ms to allow sufficient time for kernel
3550 * drivers to recover incases like SSR.
3551 */
3552 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003553 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303554 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003555 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003556}
3557
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003558static int check_input_parameters(uint32_t sample_rate,
3559 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003560 int channel_count,
3561 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003562{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003563 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003564
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303565 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3566 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3567 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003568 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003569 !audio_extn_compr_cap_format_supported(format) &&
3570 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003571 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003572
Aalique Grahame22e49102018-12-18 14:23:57 -08003573 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3574 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3575 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3576 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3577 return -EINVAL;
3578 }
3579
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003580 switch (channel_count) {
3581 case 1:
3582 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303583 case 3:
3584 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003585 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003586 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003587 break;
3588 default:
3589 ret = -EINVAL;
3590 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003591
3592 switch (sample_rate) {
3593 case 8000:
3594 case 11025:
3595 case 12000:
3596 case 16000:
3597 case 22050:
3598 case 24000:
3599 case 32000:
3600 case 44100:
3601 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003602 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303603 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003604 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303605 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003606 break;
3607 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003608 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003609 }
3610
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003611 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003612}
3613
Naresh Tanniru04f71882018-06-26 17:46:22 +05303614
3615/** Add a value in a list if not already present.
3616 * @return true if value was successfully inserted or already present,
3617 * false if the list is full and does not contain the value.
3618 */
3619static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3620 for (size_t i = 0; i < list_length; i++) {
3621 if (list[i] == value) return true; // value is already present
3622 if (list[i] == 0) { // no values in this slot
3623 list[i] = value;
3624 return true; // value inserted
3625 }
3626 }
3627 return false; // could not insert value
3628}
3629
3630/** Add channel_mask in supported_channel_masks if not already present.
3631 * @return true if channel_mask was successfully inserted or already present,
3632 * false if supported_channel_masks is full and does not contain channel_mask.
3633 */
3634static void register_channel_mask(audio_channel_mask_t channel_mask,
3635 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3636 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3637 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3638}
3639
3640/** Add format in supported_formats if not already present.
3641 * @return true if format was successfully inserted or already present,
3642 * false if supported_formats is full and does not contain format.
3643 */
3644static void register_format(audio_format_t format,
3645 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3646 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3647 "%s: stream can not declare supporting its format %x", __func__, format);
3648}
3649/** Add sample_rate in supported_sample_rates if not already present.
3650 * @return true if sample_rate was successfully inserted or already present,
3651 * false if supported_sample_rates is full and does not contain sample_rate.
3652 */
3653static void register_sample_rate(uint32_t sample_rate,
3654 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3655 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3656 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3657}
3658
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003659static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3660{
3661 uint32_t high = num1, low = num2, temp = 0;
3662
3663 if (!num1 || !num2)
3664 return 0;
3665
3666 if (num1 < num2) {
3667 high = num2;
3668 low = num1;
3669 }
3670
3671 while (low != 0) {
3672 temp = low;
3673 low = high % low;
3674 high = temp;
3675 }
3676 return (num1 * num2)/high;
3677}
3678
3679static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3680{
3681 uint32_t remainder = 0;
3682
3683 if (!multiplier)
3684 return num;
3685
3686 remainder = num % multiplier;
3687 if (remainder)
3688 num += (multiplier - remainder);
3689
3690 return num;
3691}
3692
Aalique Grahame22e49102018-12-18 14:23:57 -08003693static size_t get_stream_buffer_size(size_t duration_ms,
3694 uint32_t sample_rate,
3695 audio_format_t format,
3696 int channel_count,
3697 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003698{
3699 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003700 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003701
Aalique Grahame22e49102018-12-18 14:23:57 -08003702 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003703 if (is_low_latency)
3704 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303705
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003706 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003707 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003708
Ralf Herzbd08d632018-09-28 15:50:49 +02003709 /* make sure the size is multiple of 32 bytes and additionally multiple of
3710 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003711 * At 48 kHz mono 16-bit PCM:
3712 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3713 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003714 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003715 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003716 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003717
3718 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003719}
3720
Aalique Grahame22e49102018-12-18 14:23:57 -08003721static size_t get_input_buffer_size(uint32_t sample_rate,
3722 audio_format_t format,
3723 int channel_count,
3724 bool is_low_latency)
3725{
3726 /* Don't know if USB HIFI in this context so use true to be conservative */
3727 if (check_input_parameters(sample_rate, format, channel_count,
3728 true /*is_usb_hifi */) != 0)
3729 return 0;
3730
3731 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3732 sample_rate,
3733 format,
3734 channel_count,
3735 is_low_latency);
3736}
3737
Ashish Jain058165c2016-09-28 23:18:48 +05303738static size_t get_output_period_size(uint32_t sample_rate,
3739 audio_format_t format,
3740 int channel_count,
3741 int duration /*in millisecs*/)
3742{
3743 size_t size = 0;
3744 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3745
3746 if ((duration == 0) || (sample_rate == 0) ||
3747 (bytes_per_sample == 0) || (channel_count == 0)) {
3748 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3749 bytes_per_sample, channel_count);
3750 return -EINVAL;
3751 }
3752
3753 size = (sample_rate *
3754 duration *
3755 bytes_per_sample *
3756 channel_count) / 1000;
3757 /*
3758 * To have same PCM samples for all channels, the buffer size requires to
3759 * be multiple of (number of channels * bytes per sample)
3760 * For writes to succeed, the buffer must be written at address which is multiple of 32
3761 */
3762 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3763
3764 return (size/(channel_count * bytes_per_sample));
3765}
3766
Zhou Song48453a02018-01-10 17:50:59 +08003767static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303768{
3769 uint64_t actual_frames_rendered = 0;
3770 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3771
3772 /* This adjustment accounts for buffering after app processor.
3773 * It is based on estimated DSP latency per use case, rather than exact.
3774 */
3775 int64_t platform_latency = platform_render_latency(out->usecase) *
3776 out->sample_rate / 1000000LL;
3777
Zhou Song48453a02018-01-10 17:50:59 +08003778 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303779 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3780 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3781 * hence only estimate.
3782 */
3783 int64_t signed_frames = out->written - kernel_buffer_size;
3784
3785 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3786
Zhou Song48453a02018-01-10 17:50:59 +08003787 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303788 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003789 if (timestamp != NULL )
3790 *timestamp = out->writeAt;
3791 } else if (timestamp != NULL) {
3792 clock_gettime(CLOCK_MONOTONIC, timestamp);
3793 }
3794 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303795
3796 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3797 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3798 (long long int)out->written, (int)kernel_buffer_size,
3799 audio_bytes_per_sample(out->compr_config.codec->format),
3800 popcount(out->channel_mask));
3801
3802 return actual_frames_rendered;
3803}
3804
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003805static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3806{
3807 struct stream_out *out = (struct stream_out *)stream;
3808
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003809 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003810}
3811
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003812static int out_set_sample_rate(struct audio_stream *stream __unused,
3813 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003814{
3815 return -ENOSYS;
3816}
3817
3818static size_t out_get_buffer_size(const struct audio_stream *stream)
3819{
3820 struct stream_out *out = (struct stream_out *)stream;
3821
Varun Balaraje49253e2017-07-06 19:48:56 +05303822 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303823 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303824 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303825 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3826 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3827 else
3828 return out->compr_config.fragment_size;
3829 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003830 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003831 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3832 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 +05303833 else if (is_offload_usecase(out->usecase) &&
3834 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303835 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003836
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003837 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003838 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003839}
3840
3841static uint32_t out_get_channels(const struct audio_stream *stream)
3842{
3843 struct stream_out *out = (struct stream_out *)stream;
3844
3845 return out->channel_mask;
3846}
3847
3848static audio_format_t out_get_format(const struct audio_stream *stream)
3849{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003850 struct stream_out *out = (struct stream_out *)stream;
3851
3852 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003853}
3854
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003855static int out_set_format(struct audio_stream *stream __unused,
3856 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003857{
3858 return -ENOSYS;
3859}
3860
3861static int out_standby(struct audio_stream *stream)
3862{
3863 struct stream_out *out = (struct stream_out *)stream;
3864 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003865 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003866
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303867 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3868 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003869
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003870 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003871 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003872 if (adev->adm_deregister_stream)
3873 adev->adm_deregister_stream(adev->adm_data, out->handle);
3874
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003875 if (is_offload_usecase(out->usecase))
3876 stop_compressed_output_l(out);
3877
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003878 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003879 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003880 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3881 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303882 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003883 pthread_mutex_unlock(&adev->lock);
3884 pthread_mutex_unlock(&out->lock);
3885 ALOGD("VOIP output entered standby");
3886 return 0;
3887 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003888 if (out->pcm) {
3889 pcm_close(out->pcm);
3890 out->pcm = NULL;
3891 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003892 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3893 do_stop = out->playback_started;
3894 out->playback_started = false;
3895 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003896 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003897 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303898 out->send_next_track_params = false;
3899 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003900 out->gapless_mdata.encoder_delay = 0;
3901 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003902 if (out->compr != NULL) {
3903 compress_close(out->compr);
3904 out->compr = NULL;
3905 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003906 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003907 if (do_stop) {
3908 stop_output_stream(out);
3909 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003910 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003911 }
3912 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303913 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914 return 0;
3915}
3916
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303917static int out_on_error(struct audio_stream *stream)
3918{
3919 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003920 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303921
3922 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003923 // always send CMD_ERROR for offload streams, this
3924 // is needed e.g. when SSR happens within compress_open
3925 // since the stream is active, offload_callback_thread is also active.
3926 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
3927 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003928 }
3929 pthread_mutex_unlock(&out->lock);
3930
3931 status = out_standby(&out->stream.common);
3932
3933 lock_output_stream(out);
3934 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003935 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303936 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05303937
3938 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
3939 ALOGD("Setting previous card status if offline");
3940 out->prev_card_status_offline = true;
3941 }
3942
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303943 pthread_mutex_unlock(&out->lock);
3944
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003945 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303946}
3947
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303948/*
3949 *standby implementation without locks, assumes that the callee already
3950 *has taken adev and out lock.
3951 */
3952int out_standby_l(struct audio_stream *stream)
3953{
3954 struct stream_out *out = (struct stream_out *)stream;
3955 struct audio_device *adev = out->dev;
3956
3957 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3958 stream, out->usecase, use_case_table[out->usecase]);
3959
3960 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07003961 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303962 if (adev->adm_deregister_stream)
3963 adev->adm_deregister_stream(adev->adm_data, out->handle);
3964
3965 if (is_offload_usecase(out->usecase))
3966 stop_compressed_output_l(out);
3967
3968 out->standby = true;
3969 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3970 voice_extn_compress_voip_close_output_stream(stream);
3971 out->started = 0;
3972 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07003973 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303974 return 0;
3975 } else if (!is_offload_usecase(out->usecase)) {
3976 if (out->pcm) {
3977 pcm_close(out->pcm);
3978 out->pcm = NULL;
3979 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003980 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
3981 if (adev->haptic_pcm) {
3982 pcm_close(adev->haptic_pcm);
3983 adev->haptic_pcm = NULL;
3984 }
3985
3986 if (adev->haptic_buffer != NULL) {
3987 free(adev->haptic_buffer);
3988 adev->haptic_buffer = NULL;
3989 adev->haptic_buffer_size = 0;
3990 }
3991 adev->haptic_pcm_device_id = 0;
3992 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303993 } else {
3994 ALOGD("copl(%p):standby", out);
3995 out->send_next_track_params = false;
3996 out->is_compr_metadata_avail = false;
3997 out->gapless_mdata.encoder_delay = 0;
3998 out->gapless_mdata.encoder_padding = 0;
3999 if (out->compr != NULL) {
4000 compress_close(out->compr);
4001 out->compr = NULL;
4002 }
4003 }
4004 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004005 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304006 }
4007 ALOGD("%s: exit", __func__);
4008 return 0;
4009}
4010
Aalique Grahame22e49102018-12-18 14:23:57 -08004011static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004012{
Aalique Grahame22e49102018-12-18 14:23:57 -08004013 struct stream_out *out = (struct stream_out *)stream;
4014
4015 // We try to get the lock for consistency,
4016 // but it isn't necessary for these variables.
4017 // If we're not in standby, we may be blocked on a write.
4018 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4019 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4020 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4021
4022 if (locked) {
4023 pthread_mutex_unlock(&out->lock);
4024 }
4025
4026 // dump error info
4027 (void)error_log_dump(
4028 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4029
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004030 return 0;
4031}
4032
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004033static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4034{
4035 int ret = 0;
4036 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004037
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004038 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004039 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004040 return -EINVAL;
4041 }
4042
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304043 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004044
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004045 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4046 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304047 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004048 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004049 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4050 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304051 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004052 }
4053
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004054 ALOGV("%s new encoder delay %u and padding %u", __func__,
4055 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4056
4057 return 0;
4058}
4059
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004060static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4061{
4062 return out == adev->primary_output || out == adev->voice_tx_output;
4063}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004064
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304065// note: this call is safe only if the stream_cb is
4066// removed first in close_output_stream (as is done now).
4067static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4068{
4069 if (!stream || !parms)
4070 return;
4071
4072 struct stream_out *out = (struct stream_out *)stream;
4073 struct audio_device *adev = out->dev;
4074
4075 card_status_t status;
4076 int card;
4077 if (parse_snd_card_status(parms, &card, &status) < 0)
4078 return;
4079
4080 pthread_mutex_lock(&adev->lock);
4081 bool valid_cb = (card == adev->snd_card);
4082 pthread_mutex_unlock(&adev->lock);
4083
4084 if (!valid_cb)
4085 return;
4086
4087 lock_output_stream(out);
4088 if (out->card_status != status)
4089 out->card_status = status;
4090 pthread_mutex_unlock(&out->lock);
4091
4092 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4093 use_case_table[out->usecase],
4094 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4095
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304096 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304097 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304098 if (voice_is_call_state_active(adev) &&
4099 out == adev->primary_output) {
4100 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4101 pthread_mutex_lock(&adev->lock);
4102 voice_stop_call(adev);
4103 adev->mode = AUDIO_MODE_NORMAL;
4104 pthread_mutex_unlock(&adev->lock);
4105 }
4106 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304107 return;
4108}
4109
Kevin Rocardfce19002017-08-07 19:21:36 -07004110static int get_alive_usb_card(struct str_parms* parms) {
4111 int card;
4112 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4113 !audio_extn_usb_alive(card)) {
4114 return card;
4115 }
4116 return -ENODEV;
4117}
4118
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004119static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4120{
4121 struct stream_out *out = (struct stream_out *)stream;
4122 struct audio_device *adev = out->dev;
4123 struct str_parms *parms;
4124 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004125 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304126 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004127 bool reconfig = false;
4128 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004129
sangwoobc677242013-08-08 16:53:43 +09004130 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004131 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004132 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304133 if (!parms)
4134 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004135 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4136 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004137 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004138 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004139 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004140
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004141 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004142 * When HDMI cable is unplugged the music playback is paused and
4143 * the policy manager sends routing=0. But the audioflinger continues
4144 * to write data until standby time (3sec). As the HDMI core is
4145 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004146 * Avoid this by routing audio to speaker until standby.
4147 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004148 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4149 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304150 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004151 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4152 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004153 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304154 /*
4155 * When A2DP is disconnected the
4156 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004157 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304158 * (3sec). As BT is turned off, the write gets blocked.
4159 * Avoid this by routing audio to speaker until standby.
4160 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004161 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004162 (val == AUDIO_DEVICE_NONE) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004163 !audio_extn_a2dp_source_is_ready()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304164 val = AUDIO_DEVICE_OUT_SPEAKER;
4165 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304166 /*
4167 * When USB headset is disconnected the music platback paused
4168 * and the policy manager send routing=0. But if the USB is connected
4169 * back before the standby time, AFE is not closed and opened
4170 * when USB is connected back. So routing to speker will guarantee
4171 * AFE reconfiguration and AFE will be opend once USB is connected again
4172 */
4173 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4174 (val == AUDIO_DEVICE_NONE) &&
4175 !audio_extn_usb_connected(parms)) {
4176 val = AUDIO_DEVICE_OUT_SPEAKER;
4177 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304178 /* To avoid a2dp to sco overlapping / BT device improper state
4179 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304180 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304181 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004182 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004183 if (val &
4184 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304185 //combo usecase just by pass a2dp
4186 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304187 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304188 } else {
4189 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4190 /* update device to a2dp and don't route as BT returned error
4191 * However it is still possible a2dp routing called because
4192 * of current active device disconnection (like wired headset)
4193 */
4194 out->devices = val;
4195 pthread_mutex_unlock(&out->lock);
4196 pthread_mutex_unlock(&adev->lock);
4197 goto error;
4198 }
4199 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304200 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004201
4202 audio_devices_t new_dev = val;
4203
4204 // Workaround: If routing to an non existing usb device, fail gracefully
4205 // The routing request will otherwise block during 10 second
4206 int card;
4207 if (audio_is_usb_out_device(new_dev) &&
4208 (card = get_alive_usb_card(parms)) >= 0) {
4209
4210 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4211 pthread_mutex_unlock(&adev->lock);
4212 pthread_mutex_unlock(&out->lock);
4213 ret = -ENOSYS;
4214 goto routing_fail;
4215 }
4216
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004217 /*
4218 * select_devices() call below switches all the usecases on the same
4219 * backend to the new device. Refer to check_usecases_codec_backend() in
4220 * the select_devices(). But how do we undo this?
4221 *
4222 * For example, music playback is active on headset (deep-buffer usecase)
4223 * and if we go to ringtones and select a ringtone, low-latency usecase
4224 * will be started on headset+speaker. As we can't enable headset+speaker
4225 * and headset devices at the same time, select_devices() switches the music
4226 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4227 * So when the ringtone playback is completed, how do we undo the same?
4228 *
4229 * We are relying on the out_set_parameters() call on deep-buffer output,
4230 * once the ringtone playback is ended.
4231 * NOTE: We should not check if the current devices are same as new devices.
4232 * Because select_devices() must be called to switch back the music
4233 * playback to headset.
4234 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004235 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004236 audio_devices_t new_dev = val;
4237 bool same_dev = out->devices == new_dev;
4238 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004239
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004240 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004241 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004242 if (adev->mode == AUDIO_MODE_IN_CALL) {
4243 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004244 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4245 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4246 audio_extn_usb_set_service_interval(true /*playback*/,
4247 service_interval,
4248 &reconfig);
4249 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4250 }
4251 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004252 }
4253 } else {
4254 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004255 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004256 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004257 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004258
4259 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004260 if (!same_dev) {
4261 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304262 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4263 adev->perf_lock_opts,
4264 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004265 if (adev->adm_on_routing_change)
4266 adev->adm_on_routing_change(adev->adm_data,
4267 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004268 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304269 if (!bypass_a2dp) {
4270 select_devices(adev, out->usecase);
4271 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004272 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4273 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4274 else
4275 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304276 select_devices(adev, out->usecase);
4277 out->devices = new_dev;
4278 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004279
4280 if (!same_dev) {
4281 // on device switch force swap, lower functions will make sure
4282 // to check if swap is allowed or not.
4283 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304284 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004285 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304286 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4287 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004288 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304289 pthread_mutex_lock(&out->compr_mute_lock);
4290 out->a2dp_compress_mute = false;
4291 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4292 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004293 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4294 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304295 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004296 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004297 }
4298
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004299 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004300 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004301
4302 /*handles device and call state changes*/
4303 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004304 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004305 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004306
4307 if (out == adev->primary_output) {
4308 pthread_mutex_lock(&adev->lock);
4309 audio_extn_set_parameters(adev, parms);
4310 pthread_mutex_unlock(&adev->lock);
4311 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004312 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004313 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004314 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004315
4316 audio_extn_dts_create_state_notifier_node(out->usecase);
4317 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4318 popcount(out->channel_mask),
4319 out->playback_started);
4320
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004321 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004322 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004323
Surendar Karkaf51b5842018-04-26 11:28:38 +05304324 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4325 sizeof(value));
4326 if (err >= 0) {
4327 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4328 audio_extn_send_dual_mono_mixing_coefficients(out);
4329 }
4330
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304331 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4332 if (err >= 0) {
4333 strlcpy(out->profile, value, sizeof(out->profile));
4334 ALOGV("updating stream profile with value '%s'", out->profile);
4335 lock_output_stream(out);
4336 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4337 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004338 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304339 out->sample_rate, out->bit_width,
4340 out->channel_mask, out->profile,
4341 &out->app_type_cfg);
4342 pthread_mutex_unlock(&out->lock);
4343 }
4344
Alexy Joseph98988832017-01-13 14:56:59 -08004345 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004346 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4347 // and vendor.audio.hal.output.suspend.supported is set to true
4348 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004349 //check suspend parameter only for low latency and if the property
4350 //is enabled
4351 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4352 ALOGI("%s: got suspend_playback %s", __func__, value);
4353 lock_output_stream(out);
4354 if (!strncmp(value, "false", 5)) {
4355 //suspend_playback=false is supposed to set QOS value back to 75%
4356 //the mixer control sent with value Enable will achieve that
4357 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4358 } else if (!strncmp (value, "true", 4)) {
4359 //suspend_playback=true is supposed to remove QOS value
4360 //resetting the mixer control will set the default value
4361 //for the mixer control which is Disable and this removes the QOS vote
4362 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4363 } else {
4364 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4365 " got %s", __func__, value);
4366 ret = -1;
4367 }
4368
4369 if (ret != 0) {
4370 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4371 __func__, out->pm_qos_mixer_path, ret);
4372 }
4373
4374 pthread_mutex_unlock(&out->lock);
4375 }
4376 }
4377 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004378 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304379error:
Eric Laurent994a6932013-07-17 11:51:42 -07004380 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004381 return ret;
4382}
4383
Paul McLeana50b7332018-12-17 08:24:21 -07004384static int in_set_microphone_direction(const struct audio_stream_in *stream,
4385 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004386 struct stream_in *in = (struct stream_in *)stream;
4387
4388 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4389
4390 in->direction = dir;
4391
4392 if (in->standby)
4393 return 0;
4394
4395 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004396}
4397
4398static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004399 struct stream_in *in = (struct stream_in *)stream;
4400
4401 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4402
4403 if (zoom > 1.0 || zoom < -1.0)
4404 return -EINVAL;
4405
4406 in->zoom = zoom;
4407
4408 if (in->standby)
4409 return 0;
4410
4411 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004412}
4413
4414
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004415static bool stream_get_parameter_channels(struct str_parms *query,
4416 struct str_parms *reply,
4417 audio_channel_mask_t *supported_channel_masks) {
4418 int ret = -1;
4419 char value[512];
4420 bool first = true;
4421 size_t i, j;
4422
4423 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4424 ret = 0;
4425 value[0] = '\0';
4426 i = 0;
4427 while (supported_channel_masks[i] != 0) {
4428 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4429 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4430 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304431 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004432
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304433 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004434 first = false;
4435 break;
4436 }
4437 }
4438 i++;
4439 }
4440 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4441 }
4442 return ret == 0;
4443}
4444
4445static bool stream_get_parameter_formats(struct str_parms *query,
4446 struct str_parms *reply,
4447 audio_format_t *supported_formats) {
4448 int ret = -1;
4449 char value[256];
4450 size_t i, j;
4451 bool first = true;
4452
4453 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4454 ret = 0;
4455 value[0] = '\0';
4456 i = 0;
4457 while (supported_formats[i] != 0) {
4458 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4459 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4460 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304461 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004462 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304463 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004464 first = false;
4465 break;
4466 }
4467 }
4468 i++;
4469 }
4470 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4471 }
4472 return ret == 0;
4473}
4474
4475static bool stream_get_parameter_rates(struct str_parms *query,
4476 struct str_parms *reply,
4477 uint32_t *supported_sample_rates) {
4478
4479 int i;
4480 char value[256];
4481 int ret = -1;
4482 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4483 ret = 0;
4484 value[0] = '\0';
4485 i=0;
4486 int cursor = 0;
4487 while (supported_sample_rates[i]) {
4488 int avail = sizeof(value) - cursor;
4489 ret = snprintf(value + cursor, avail, "%s%d",
4490 cursor > 0 ? "|" : "",
4491 supported_sample_rates[i]);
4492 if (ret < 0 || ret >= avail) {
4493 // if cursor is at the last element of the array
4494 // overwrite with \0 is duplicate work as
4495 // snprintf already put a \0 in place.
4496 // else
4497 // we had space to write the '|' at value[cursor]
4498 // (which will be overwritten) or no space to fill
4499 // the first element (=> cursor == 0)
4500 value[cursor] = '\0';
4501 break;
4502 }
4503 cursor += ret;
4504 ++i;
4505 }
4506 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4507 value);
4508 }
4509 return ret >= 0;
4510}
4511
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004512static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4513{
4514 struct stream_out *out = (struct stream_out *)stream;
4515 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004516 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004517 char value[256];
4518 struct str_parms *reply = str_parms_create();
4519 size_t i, j;
4520 int ret;
4521 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004522
4523 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004524 if (reply) {
4525 str_parms_destroy(reply);
4526 }
4527 if (query) {
4528 str_parms_destroy(query);
4529 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004530 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4531 return NULL;
4532 }
4533
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004534 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004535 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4536 if (ret >= 0) {
4537 value[0] = '\0';
4538 i = 0;
4539 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004540 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4541 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004542 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004543 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004544 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004545 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004546 first = false;
4547 break;
4548 }
4549 }
4550 i++;
4551 }
4552 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4553 str = str_parms_to_str(reply);
4554 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004555 voice_extn_out_get_parameters(out, query, reply);
4556 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004557 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004558
Alexy Joseph62142aa2015-11-16 15:10:34 -08004559
4560 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4561 if (ret >= 0) {
4562 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304563 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4564 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004565 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304566 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004567 } else {
4568 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304569 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004570 }
4571 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004572 if (str)
4573 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004574 str = str_parms_to_str(reply);
4575 }
4576
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004577 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4578 if (ret >= 0) {
4579 value[0] = '\0';
4580 i = 0;
4581 first = true;
4582 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004583 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4584 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004585 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004586 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004587 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004588 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004589 first = false;
4590 break;
4591 }
4592 }
4593 i++;
4594 }
4595 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004596 if (str)
4597 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004598 str = str_parms_to_str(reply);
4599 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004600
4601 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4602 if (ret >= 0) {
4603 value[0] = '\0';
4604 i = 0;
4605 first = true;
4606 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004607 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4608 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004609 if (!first) {
4610 strlcat(value, "|", sizeof(value));
4611 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004612 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004613 first = false;
4614 break;
4615 }
4616 }
4617 i++;
4618 }
4619 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4620 if (str)
4621 free(str);
4622 str = str_parms_to_str(reply);
4623 }
4624
Alexy Joseph98988832017-01-13 14:56:59 -08004625 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4626 //only low latency track supports suspend_resume
4627 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004628 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004629 if (str)
4630 free(str);
4631 str = str_parms_to_str(reply);
4632 }
4633
4634
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004635 str_parms_destroy(query);
4636 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004637 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004638 return str;
4639}
4640
4641static uint32_t out_get_latency(const struct audio_stream_out *stream)
4642{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004643 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004644 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004645 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004646
Alexy Josephaa54c872014-12-03 02:46:47 -08004647 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304648 lock_output_stream(out);
4649 latency = audio_extn_utils_compress_get_dsp_latency(out);
4650 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004651 } else if ((out->realtime) ||
4652 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004653 // since the buffer won't be filled up faster than realtime,
4654 // return a smaller number
4655 if (out->config.rate)
4656 period_ms = (out->af_period_multiplier * out->config.period_size *
4657 1000) / (out->config.rate);
4658 else
4659 period_ms = 0;
4660 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004661 } else {
4662 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004663 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004664 }
4665
yidongh0515e042017-07-06 15:00:34 +08004666 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004667 latency += audio_extn_a2dp_get_encoder_latency();
4668
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304669 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004670 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004671}
4672
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304673static float AmpToDb(float amplification)
4674{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304675 float db = DSD_VOLUME_MIN_DB;
4676 if (amplification > 0) {
4677 db = 20 * log10(amplification);
4678 if(db < DSD_VOLUME_MIN_DB)
4679 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304680 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304681 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304682}
4683
Arun Mirpuri5d170872019-03-26 13:21:31 -07004684static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4685 float right)
4686{
4687 struct stream_out *out = (struct stream_out *)stream;
4688 long volume = 0;
4689 char mixer_ctl_name[128] = "";
4690 struct audio_device *adev = out->dev;
4691 struct mixer_ctl *ctl = NULL;
4692 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4693 PCM_PLAYBACK);
4694
4695 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4696 "Playback %d Volume", pcm_device_id);
4697 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4698 if (!ctl) {
4699 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4700 __func__, mixer_ctl_name);
4701 return -EINVAL;
4702 }
4703 if (left != right)
4704 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4705 __func__, left, right);
4706 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4707 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4708 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4709 __func__, mixer_ctl_name, volume);
4710 return -EINVAL;
4711 }
4712 return 0;
4713}
4714
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304715static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4716 float right)
4717{
4718 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304719 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304720 char mixer_ctl_name[128];
4721 struct audio_device *adev = out->dev;
4722 struct mixer_ctl *ctl;
4723 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4724 PCM_PLAYBACK);
4725
4726 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4727 "Compress Playback %d Volume", pcm_device_id);
4728 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4729 if (!ctl) {
4730 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4731 __func__, mixer_ctl_name);
4732 return -EINVAL;
4733 }
4734 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4735 __func__, mixer_ctl_name, left, right);
4736 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4737 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4738 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4739
4740 return 0;
4741}
4742
Zhou Song2b8f28f2017-09-11 10:51:38 +08004743static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4744 float right)
4745{
4746 struct stream_out *out = (struct stream_out *)stream;
4747 char mixer_ctl_name[] = "App Type Gain";
4748 struct audio_device *adev = out->dev;
4749 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304750 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004751
4752 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4753 if (!ctl) {
4754 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4755 __func__, mixer_ctl_name);
4756 return -EINVAL;
4757 }
4758
4759 set_values[0] = 0; //0: Rx Session 1:Tx Session
4760 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304761 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4762 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004763
4764 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4765 return 0;
4766}
4767
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304768static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4769 float right)
4770{
4771 struct stream_out *out = (struct stream_out *)stream;
4772 /* Volume control for pcm playback */
4773 if (left != right) {
4774 return -EINVAL;
4775 } else {
4776 char mixer_ctl_name[128];
4777 struct audio_device *adev = out->dev;
4778 struct mixer_ctl *ctl;
4779 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4780 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4781 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4782 if (!ctl) {
4783 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4784 return -EINVAL;
4785 }
4786
4787 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4788 int ret = mixer_ctl_set_value(ctl, 0, volume);
4789 if (ret < 0) {
4790 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4791 return -EINVAL;
4792 }
4793
4794 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4795
4796 return 0;
4797 }
4798}
4799
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004800static int out_set_volume(struct audio_stream_out *stream, float left,
4801 float right)
4802{
Eric Laurenta9024de2013-04-04 09:19:12 -07004803 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004804 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304805 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004806
Arun Mirpuri5d170872019-03-26 13:21:31 -07004807 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07004808 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4809 /* only take left channel into account: the API is for stereo anyway */
4810 out->muted = (left == 0.0f);
4811 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004812 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304813 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004814 /*
4815 * Set mute or umute on HDMI passthrough stream.
4816 * Only take left channel into account.
4817 * Mute is 0 and unmute 1
4818 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304819 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304820 } else if (out->format == AUDIO_FORMAT_DSD){
4821 char mixer_ctl_name[128] = "DSD Volume";
4822 struct audio_device *adev = out->dev;
4823 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4824
4825 if (!ctl) {
4826 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4827 __func__, mixer_ctl_name);
4828 return -EINVAL;
4829 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304830 volume[0] = (long)(AmpToDb(left));
4831 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304832 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4833 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004834 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304835 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07004836 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304837 if (!out->a2dp_compress_mute)
4838 ret = out_set_compr_volume(stream, left, right);
4839 out->volume_l = left;
4840 out->volume_r = right;
4841 pthread_mutex_unlock(&out->compr_mute_lock);
4842 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004843 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004844 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004845 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4846 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4847 if (!out->standby) {
4848 audio_extn_utils_send_app_type_gain(out->dev,
4849 out->app_type_cfg.app_type,
4850 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004851 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004852 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004853 out->volume_l = left;
4854 out->volume_r = right;
4855 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07004856 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4857 ALOGV("%s: MMAP set volume called", __func__);
4858 if (!out->standby)
4859 ret = out_set_mmap_volume(stream, left, right);
4860 out->volume_l = left;
4861 out->volume_r = right;
4862 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304863 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304864 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4865 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304866 /* Volume control for pcm playback */
4867 if (!out->standby)
4868 ret = out_set_pcm_volume(stream, left, right);
4869 else
4870 out->apply_volume = true;
4871
4872 out->volume_l = left;
4873 out->volume_r = right;
4874 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004875 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004876
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004877 return -ENOSYS;
4878}
4879
Zhou Songc9672822017-08-16 16:01:39 +08004880static void update_frames_written(struct stream_out *out, size_t bytes)
4881{
4882 size_t bpf = 0;
4883
4884 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4885 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4886 bpf = 1;
4887 else if (!is_offload_usecase(out->usecase))
4888 bpf = audio_bytes_per_sample(out->format) *
4889 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004890
4891 pthread_mutex_lock(&out->position_query_lock);
4892 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004893 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004894 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4895 }
4896 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004897}
4898
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004899int split_and_write_audio_haptic_data(struct stream_out *out,
4900 const void *buffer, size_t bytes_to_write)
4901{
4902 struct audio_device *adev = out->dev;
4903
4904 int ret = 0;
4905 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4906 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
4907 size_t frame_size = channel_count * bytes_per_sample;
4908 size_t frame_count = bytes_to_write / frame_size;
4909
4910 bool force_haptic_path =
4911 property_get_bool("vendor.audio.test_haptic", false);
4912
4913 // extract Haptics data from Audio buffer
4914 bool alloc_haptic_buffer = false;
4915 int haptic_channel_count = adev->haptics_config.channels;
4916 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
4917 size_t audio_frame_size = frame_size - haptic_frame_size;
4918 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
4919
4920 if (adev->haptic_buffer == NULL) {
4921 alloc_haptic_buffer = true;
4922 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
4923 free(adev->haptic_buffer);
4924 adev->haptic_buffer_size = 0;
4925 alloc_haptic_buffer = true;
4926 }
4927
4928 if (alloc_haptic_buffer) {
4929 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
4930 adev->haptic_buffer_size = total_haptic_buffer_size;
4931 }
4932
4933 size_t src_index = 0, aud_index = 0, hap_index = 0;
4934 uint8_t *audio_buffer = (uint8_t *)buffer;
4935 uint8_t *haptic_buffer = adev->haptic_buffer;
4936
4937 // This is required for testing only. This works for stereo data only.
4938 // One channel is fed to audio stream and other to haptic stream for testing.
4939 if (force_haptic_path)
4940 audio_frame_size = haptic_frame_size = bytes_per_sample;
4941
4942 for (size_t i = 0; i < frame_count; i++) {
4943 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
4944 audio_frame_size);
4945 aud_index += audio_frame_size;
4946 src_index += audio_frame_size;
4947
4948 if (adev->haptic_pcm)
4949 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
4950 haptic_frame_size);
4951 hap_index += haptic_frame_size;
4952 src_index += haptic_frame_size;
4953
4954 // This is required for testing only.
4955 // Discard haptic channel data.
4956 if (force_haptic_path)
4957 src_index += haptic_frame_size;
4958 }
4959
4960 // write to audio pipeline
4961 ret = pcm_write(out->pcm, (void *)audio_buffer,
4962 frame_count * audio_frame_size);
4963
4964 // write to haptics pipeline
4965 if (adev->haptic_pcm)
4966 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
4967 frame_count * haptic_frame_size);
4968
4969 return ret;
4970}
4971
Aalique Grahame22e49102018-12-18 14:23:57 -08004972#ifdef NO_AUDIO_OUT
4973static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
4974 const void *buffer __unused, size_t bytes)
4975{
4976 struct stream_out *out = (struct stream_out *)stream;
4977
4978 /* No Output device supported other than BT for playback.
4979 * Sleep for the amount of buffer duration
4980 */
4981 lock_output_stream(out);
4982 usleep(bytes * 1000000 / audio_stream_out_frame_size(
4983 (const struct audio_stream_out *)&out->stream) /
4984 out_get_sample_rate(&out->stream.common));
4985 pthread_mutex_unlock(&out->lock);
4986 return bytes;
4987}
4988#endif
4989
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004990static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
4991 size_t bytes)
4992{
4993 struct stream_out *out = (struct stream_out *)stream;
4994 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07004995 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05304996 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07004997 const size_t frame_size = audio_stream_out_frame_size(stream);
4998 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05304999 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005000
Haynes Mathew George380745d2017-10-04 15:27:45 -07005001 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005002 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305003
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305004 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005005
Dhananjay Kumarac341582017-02-23 23:42:25 +05305006 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305007 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305008 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5009 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005010 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305011 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305012 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305013 ALOGD(" %s: sound card is not active/SSR state", __func__);
5014 ret= -EIO;
5015 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305016 }
5017 }
5018
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305019 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305020 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305021 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305022 goto exit;
5023 }
5024
Haynes Mathew George16081042017-05-31 17:16:49 -07005025 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5026 ret = -EINVAL;
5027 goto exit;
5028 }
5029
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305030 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5031 !out->is_iec61937_info_available) {
5032
5033 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5034 out->is_iec61937_info_available = true;
5035 } else if (audio_extn_passthru_is_enabled()) {
5036 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305037 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305038
5039 if((out->format == AUDIO_FORMAT_DTS) ||
5040 (out->format == AUDIO_FORMAT_DTS_HD)) {
5041 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5042 buffer, bytes);
5043 if (ret) {
5044 if (ret != -ENOSYS) {
5045 out->is_iec61937_info_available = false;
5046 ALOGD("iec61937 transmission info not yet updated retry");
5047 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305048 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305049 /* if stream has started and after that there is
5050 * stream config change (iec transmission config)
5051 * then trigger select_device to update backend configuration.
5052 */
5053 out->stream_config_changed = true;
5054 pthread_mutex_lock(&adev->lock);
5055 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305056 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
5057 ret = -EINVAL;
5058 goto exit;
5059 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305060 pthread_mutex_unlock(&adev->lock);
5061 out->stream_config_changed = false;
5062 out->is_iec61937_info_available = true;
5063 }
5064 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305065
Garmond Leung317cbf12017-09-13 16:20:50 -07005066 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305067 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5068 (out->is_iec61937_info_available == true)) {
5069 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5070 ret = -EINVAL;
5071 goto exit;
5072 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305073 }
5074 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305075
5076 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005077 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005078 if (!(out->devices &
5079 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305080 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305081 ret = -EIO;
5082 goto exit;
5083 }
5084 }
5085 }
5086
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005087 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005088 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005089 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005090 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5091 ret = voice_extn_compress_voip_start_output_stream(out);
5092 else
5093 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005094 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005095 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005096 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005097 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005098 goto exit;
5099 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305100 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005101 if (last_known_cal_step != -1) {
5102 ALOGD("%s: retry previous failed cal level set", __func__);
5103 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305104 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005105 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305106
5107 if ((out->is_iec61937_info_available == true) &&
5108 (audio_extn_passthru_is_passthrough_stream(out))&&
5109 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5110 ret = -EINVAL;
5111 goto exit;
5112 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305113 if (out->set_dual_mono)
5114 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005115 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005116
Ashish Jain81eb2a82015-05-13 10:52:34 +05305117 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005118 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305119 adev->is_channel_status_set = true;
5120 }
5121
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305122 if ((adev->use_old_pspd_mix_ctrl == true) &&
5123 (out->pspd_coeff_sent == false)) {
5124 /*
5125 * Need to resend pspd coefficients after stream started for
5126 * older kernel version as it does not save the coefficients
5127 * and also stream has to be started for coeff to apply.
5128 */
5129 usecase = get_usecase_from_list(adev, out->usecase);
5130 if (usecase != NULL) {
5131 audio_extn_set_custom_mtmx_params(adev, usecase, true);
5132 out->pspd_coeff_sent = true;
5133 }
5134 }
5135
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005136 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005137 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005138 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005139 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005140 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5141 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305142 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5143 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005144 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305145 out->send_next_track_params = false;
5146 out->is_compr_metadata_avail = false;
5147 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005148 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305149 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305150 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005151
Ashish Jain83a6cc22016-06-28 14:34:17 +05305152 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305153 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305154 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305155 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005156 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305157 return -EINVAL;
5158 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305159 audio_format_t dst_format = out->hal_op_format;
5160 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305161
Dieter Luecking5d57def2018-09-07 14:23:37 +02005162 /* prevent division-by-zero */
5163 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5164 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5165 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5166 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305167 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005168 ATRACE_END();
5169 return -EINVAL;
5170 }
5171
Ashish Jainf1eaa582016-05-23 20:54:24 +05305172 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5173 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5174
Ashish Jain83a6cc22016-06-28 14:34:17 +05305175 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305176 dst_format,
5177 buffer,
5178 src_format,
5179 frames);
5180
Ashish Jain83a6cc22016-06-28 14:34:17 +05305181 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305182 bytes_to_write);
5183
5184 /*Convert written bytes in audio flinger format*/
5185 if (ret > 0)
5186 ret = ((ret * format_to_bitwidth_table[out->format]) /
5187 format_to_bitwidth_table[dst_format]);
5188 }
5189 } else
5190 ret = compress_write(out->compr, buffer, bytes);
5191
Zhou Songc9672822017-08-16 16:01:39 +08005192 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5193 update_frames_written(out, bytes);
5194
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305195 if (ret < 0)
5196 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005197 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305198 /*msg to cb thread only if non blocking write is enabled*/
5199 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305200 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005201 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305202 } else if (-ENETRESET == ret) {
5203 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305204 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305205 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305206 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005207 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305208 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005209 }
Ashish Jain5106d362016-05-11 19:23:33 +05305210
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305211 /* Call compr start only when non-zero bytes of data is there to be rendered */
5212 if (!out->playback_started && ret > 0) {
5213 int status = compress_start(out->compr);
5214 if (status < 0) {
5215 ret = status;
5216 ALOGE("%s: compr start failed with err %d", __func__, errno);
5217 goto exit;
5218 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005219 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005220 out->playback_started = 1;
5221 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005222
5223 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5224 popcount(out->channel_mask),
5225 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005226 }
5227 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005228 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005229 return ret;
5230 } else {
5231 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005232 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005233 if (out->muted)
5234 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005235 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5236 __func__, frames, frame_size, bytes_to_write);
5237
Aalique Grahame22e49102018-12-18 14:23:57 -08005238 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aalique Grahame22e49102018-12-18 14:23:57 -08005239 out->usecase == USECASE_INCALL_MUSIC_UPLINK2) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005240 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5241 int16_t *src = (int16_t *)buffer;
5242 int16_t *dst = (int16_t *)buffer;
5243
5244 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5245 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005246 "out_write called for %s use case with wrong properties",
5247 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005248
5249 /*
5250 * FIXME: this can be removed once audio flinger mixer supports
5251 * mono output
5252 */
5253
5254 /*
5255 * Code below goes over each frame in the buffer and adds both
5256 * L and R samples and then divides by 2 to convert to mono
5257 */
5258 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5259 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5260 }
5261 bytes_to_write /= 2;
5262 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005263
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305264 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005265
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005266 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005267
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005268 if (out->config.rate)
5269 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5270 out->config.rate;
5271
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005272 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005273 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5274
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005275 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005276 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005277 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305278 out->convert_buffer != NULL) {
5279
5280 memcpy_by_audio_format(out->convert_buffer,
5281 out->hal_op_format,
5282 buffer,
5283 out->hal_ip_format,
5284 out->config.period_size * out->config.channels);
5285
5286 ret = pcm_write(out->pcm, out->convert_buffer,
5287 (out->config.period_size *
5288 out->config.channels *
5289 format_to_bitwidth_table[out->hal_op_format]));
5290 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305291 /*
5292 * To avoid underrun in DSP when the application is not pumping
5293 * data at required rate, check for the no. of bytes and ignore
5294 * pcm_write if it is less than actual buffer size.
5295 * It is a work around to a change in compress VOIP driver.
5296 */
5297 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5298 bytes < (out->config.period_size * out->config.channels *
5299 audio_bytes_per_sample(out->format))) {
5300 size_t voip_buf_size =
5301 out->config.period_size * out->config.channels *
5302 audio_bytes_per_sample(out->format);
5303 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5304 __func__, bytes, voip_buf_size);
5305 usleep(((uint64_t)voip_buf_size - bytes) *
5306 1000000 / audio_stream_out_frame_size(stream) /
5307 out_get_sample_rate(&out->stream.common));
5308 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005309 } else {
5310 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5311 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5312 else
5313 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5314 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305315 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005316
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005317 release_out_focus(out);
5318
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305319 if (ret < 0)
5320 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005321 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305322 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005323 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005324 }
5325
5326exit:
Zhou Songc9672822017-08-16 16:01:39 +08005327 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305328 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305329 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305330 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005331 pthread_mutex_unlock(&out->lock);
5332
5333 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005334 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005335 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305336 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305337 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305338 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305339 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305340 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305341 out->standby = true;
5342 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305343 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005344 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5345 /* prevent division-by-zero */
5346 uint32_t stream_size = audio_stream_out_frame_size(stream);
5347 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005348
Dieter Luecking5d57def2018-09-07 14:23:37 +02005349 if ((stream_size == 0) || (srate == 0)) {
5350 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5351 ATRACE_END();
5352 return -EINVAL;
5353 }
5354 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5355 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005356 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305357 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005358 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005359 return ret;
5360 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005361 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005362 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005363 return bytes;
5364}
5365
5366static int out_get_render_position(const struct audio_stream_out *stream,
5367 uint32_t *dsp_frames)
5368{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005369 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005370
5371 if (dsp_frames == NULL)
5372 return -EINVAL;
5373
5374 *dsp_frames = 0;
5375 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005376 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305377
5378 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5379 * this operation and adev_close_output_stream(where out gets reset).
5380 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305381 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005382 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305383 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005384 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305385 return 0;
5386 }
5387
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005388 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305389 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305390 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005391 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305392 if (ret < 0)
5393 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005394 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305395 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005396 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305397 if (-ENETRESET == ret) {
5398 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305399 out->card_status = CARD_STATUS_OFFLINE;
5400 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305401 } else if(ret < 0) {
5402 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305403 ret = -EINVAL;
5404 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305405 /*
5406 * Handle corner case where compress session is closed during SSR
5407 * and timestamp is queried
5408 */
5409 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305410 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305411 } else if (out->prev_card_status_offline) {
5412 ALOGE("ERROR: previously sound card was offline,return error");
5413 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305414 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305415 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005416 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305417 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305418 pthread_mutex_unlock(&out->lock);
5419 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005420 } else if (audio_is_linear_pcm(out->format)) {
5421 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005422 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005423 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005424 } else
5425 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005426}
5427
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005428static int out_add_audio_effect(const struct audio_stream *stream __unused,
5429 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005430{
5431 return 0;
5432}
5433
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005434static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5435 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005436{
5437 return 0;
5438}
5439
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005440static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5441 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005442{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305443 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005444}
5445
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005446static int out_get_presentation_position(const struct audio_stream_out *stream,
5447 uint64_t *frames, struct timespec *timestamp)
5448{
5449 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305450 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005451 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005452
Ashish Jain5106d362016-05-11 19:23:33 +05305453 /* below piece of code is not guarded against any lock because audioFliner serializes
5454 * this operation and adev_close_output_stream( where out gets reset).
5455 */
5456 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305457 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005458 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305459 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5460 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5461 return 0;
5462 }
5463
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005464 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005465
Ashish Jain5106d362016-05-11 19:23:33 +05305466 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5467 ret = compress_get_tstamp(out->compr, &dsp_frames,
5468 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005469 // Adjustment accounts for A2dp encoder latency with offload usecases
5470 // Note: Encoder latency is returned in ms.
5471 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5472 unsigned long offset =
5473 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5474 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5475 }
Ashish Jain5106d362016-05-11 19:23:33 +05305476 ALOGVV("%s rendered frames %ld sample_rate %d",
5477 __func__, dsp_frames, out->sample_rate);
5478 *frames = dsp_frames;
5479 if (ret < 0)
5480 ret = -errno;
5481 if (-ENETRESET == ret) {
5482 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305483 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305484 ret = -EINVAL;
5485 } else
5486 ret = 0;
5487 /* this is the best we can do */
5488 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005489 } else {
5490 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005491 unsigned int avail;
5492 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5493 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5494 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5495 // This adjustment accounts for buffering after app processor.
5496 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005497 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005498 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005499
Weiyin Jiangd4633762018-03-16 12:05:03 +08005500 // Adjustment accounts for A2dp encoder latency with non offload usecases
5501 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5502 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5503 signed_frames -=
5504 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5505 }
5506
5507 // It would be unusual for this value to be negative, but check just in case ...
5508 if (signed_frames >= 0) {
5509 *frames = signed_frames;
5510 ret = 0;
5511 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005512 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305513 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305514 *frames = out->written;
5515 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305516 if (is_offload_usecase(out->usecase))
5517 ret = -EINVAL;
5518 else
5519 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005520 }
5521 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005522 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005523 return ret;
5524}
5525
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005526static int out_set_callback(struct audio_stream_out *stream,
5527 stream_callback_t callback, void *cookie)
5528{
5529 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005530 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005531
5532 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005533 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005534 out->client_callback = callback;
5535 out->client_cookie = cookie;
5536 if (out->adsp_hdlr_stream_handle) {
5537 ret = audio_extn_adsp_hdlr_stream_set_callback(
5538 out->adsp_hdlr_stream_handle,
5539 callback,
5540 cookie);
5541 if (ret)
5542 ALOGW("%s:adsp hdlr callback registration failed %d",
5543 __func__, ret);
5544 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005545 pthread_mutex_unlock(&out->lock);
5546 return 0;
5547}
5548
5549static int out_pause(struct audio_stream_out* stream)
5550{
5551 struct stream_out *out = (struct stream_out *)stream;
5552 int status = -ENOSYS;
5553 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005554 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005555 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005556 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005557 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305558 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305559 status = compress_pause(out->compr);
5560
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005561 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005562
Mingming Yin21854652016-04-13 11:54:02 -07005563 if (audio_extn_passthru_is_active()) {
5564 ALOGV("offload use case, pause passthru");
5565 audio_extn_passthru_on_pause(out);
5566 }
5567
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305568 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005569 audio_extn_dts_notify_playback_state(out->usecase, 0,
5570 out->sample_rate, popcount(out->channel_mask),
5571 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005572 }
5573 pthread_mutex_unlock(&out->lock);
5574 }
5575 return status;
5576}
5577
5578static int out_resume(struct audio_stream_out* stream)
5579{
5580 struct stream_out *out = (struct stream_out *)stream;
5581 int status = -ENOSYS;
5582 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005583 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005584 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005585 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005586 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005587 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305588 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305589 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005590 }
5591 if (!status) {
5592 out->offload_state = OFFLOAD_STATE_PLAYING;
5593 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305594 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005595 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5596 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005597 }
5598 pthread_mutex_unlock(&out->lock);
5599 }
5600 return status;
5601}
5602
5603static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5604{
5605 struct stream_out *out = (struct stream_out *)stream;
5606 int status = -ENOSYS;
5607 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005608 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005609 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005610 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5611 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5612 else
5613 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5614 pthread_mutex_unlock(&out->lock);
5615 }
5616 return status;
5617}
5618
5619static int out_flush(struct audio_stream_out* stream)
5620{
5621 struct stream_out *out = (struct stream_out *)stream;
5622 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005623 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005624 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005625 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005626 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5627 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005628 } else {
5629 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5630 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005631 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005632 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005633 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005634 return 0;
5635 }
5636 return -ENOSYS;
5637}
5638
Haynes Mathew George16081042017-05-31 17:16:49 -07005639static int out_stop(const struct audio_stream_out* stream)
5640{
5641 struct stream_out *out = (struct stream_out *)stream;
5642 struct audio_device *adev = out->dev;
5643 int ret = -ENOSYS;
5644
5645 ALOGV("%s", __func__);
5646 pthread_mutex_lock(&adev->lock);
5647 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5648 out->playback_started && out->pcm != NULL) {
5649 pcm_stop(out->pcm);
5650 ret = stop_output_stream(out);
5651 out->playback_started = false;
5652 }
5653 pthread_mutex_unlock(&adev->lock);
5654 return ret;
5655}
5656
5657static int out_start(const struct audio_stream_out* stream)
5658{
5659 struct stream_out *out = (struct stream_out *)stream;
5660 struct audio_device *adev = out->dev;
5661 int ret = -ENOSYS;
5662
5663 ALOGV("%s", __func__);
5664 pthread_mutex_lock(&adev->lock);
5665 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5666 !out->playback_started && out->pcm != NULL) {
5667 ret = start_output_stream(out);
5668 if (ret == 0) {
5669 out->playback_started = true;
5670 }
5671 }
5672 pthread_mutex_unlock(&adev->lock);
5673 return ret;
5674}
5675
5676/*
5677 * Modify config->period_count based on min_size_frames
5678 */
5679static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5680{
5681 int periodCountRequested = (min_size_frames + config->period_size - 1)
5682 / config->period_size;
5683 int periodCount = MMAP_PERIOD_COUNT_MIN;
5684
5685 ALOGV("%s original config.period_size = %d config.period_count = %d",
5686 __func__, config->period_size, config->period_count);
5687
5688 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5689 periodCount *= 2;
5690 }
5691 config->period_count = periodCount;
5692
5693 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5694}
5695
5696static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5697 int32_t min_size_frames,
5698 struct audio_mmap_buffer_info *info)
5699{
5700 struct stream_out *out = (struct stream_out *)stream;
5701 struct audio_device *adev = out->dev;
5702 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005703 unsigned int offset1 = 0;
5704 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005705 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005706 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005707 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005708
Arun Mirpuri5d170872019-03-26 13:21:31 -07005709 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305710 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005711 pthread_mutex_lock(&adev->lock);
5712
Sharad Sanglec6f32552018-05-04 16:15:38 +05305713 if (CARD_STATUS_OFFLINE == out->card_status ||
5714 CARD_STATUS_OFFLINE == adev->card_status) {
5715 ALOGW("out->card_status or adev->card_status offline, try again");
5716 ret = -EIO;
5717 goto exit;
5718 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005719 if (info == NULL || min_size_frames == 0) {
5720 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5721 ret = -EINVAL;
5722 goto exit;
5723 }
5724 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5725 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5726 ret = -ENOSYS;
5727 goto exit;
5728 }
5729 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5730 if (out->pcm_device_id < 0) {
5731 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5732 __func__, out->pcm_device_id, out->usecase);
5733 ret = -EINVAL;
5734 goto exit;
5735 }
5736
5737 adjust_mmap_period_count(&out->config, min_size_frames);
5738
Arun Mirpuri5d170872019-03-26 13:21:31 -07005739 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005740 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5741 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5742 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305743 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305744 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5745 out->card_status = CARD_STATUS_OFFLINE;
5746 adev->card_status = CARD_STATUS_OFFLINE;
5747 ret = -EIO;
5748 goto exit;
5749 }
5750
Haynes Mathew George16081042017-05-31 17:16:49 -07005751 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5752 step = "open";
5753 ret = -ENODEV;
5754 goto exit;
5755 }
5756 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5757 if (ret < 0) {
5758 step = "begin";
5759 goto exit;
5760 }
5761 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005762 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005763 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005764 ret = platform_get_mmap_data_fd(adev->platform,
5765 out->pcm_device_id, 0 /*playback*/,
5766 &info->shared_memory_fd,
5767 &mmap_size);
5768 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005769 // Fall back to non exclusive mode
5770 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5771 } else {
5772 if (mmap_size < buffer_size) {
5773 step = "mmap";
5774 goto exit;
5775 }
5776 // FIXME: indicate exclusive mode support by returning a negative buffer size
5777 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005778 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005779 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005780 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005781
5782 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5783 if (ret < 0) {
5784 step = "commit";
5785 goto exit;
5786 }
5787
5788 out->standby = false;
5789 ret = 0;
5790
Arun Mirpuri5d170872019-03-26 13:21:31 -07005791 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005792 __func__, info->shared_memory_address, info->buffer_size_frames);
5793
5794exit:
5795 if (ret != 0) {
5796 if (out->pcm == NULL) {
5797 ALOGE("%s: %s - %d", __func__, step, ret);
5798 } else {
5799 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5800 pcm_close(out->pcm);
5801 out->pcm = NULL;
5802 }
5803 }
5804 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305805 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005806 return ret;
5807}
5808
5809static int out_get_mmap_position(const struct audio_stream_out *stream,
5810 struct audio_mmap_position *position)
5811{
5812 struct stream_out *out = (struct stream_out *)stream;
5813 ALOGVV("%s", __func__);
5814 if (position == NULL) {
5815 return -EINVAL;
5816 }
5817 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005818 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005819 return -ENOSYS;
5820 }
5821 if (out->pcm == NULL) {
5822 return -ENOSYS;
5823 }
5824
5825 struct timespec ts = { 0, 0 };
5826 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5827 if (ret < 0) {
5828 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5829 return ret;
5830 }
Aalique Grahame90717e22018-07-18 15:54:18 -07005831 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07005832 return 0;
5833}
5834
5835
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005836/** audio_stream_in implementation **/
5837static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5838{
5839 struct stream_in *in = (struct stream_in *)stream;
5840
5841 return in->config.rate;
5842}
5843
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005844static int in_set_sample_rate(struct audio_stream *stream __unused,
5845 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005846{
5847 return -ENOSYS;
5848}
5849
5850static size_t in_get_buffer_size(const struct audio_stream *stream)
5851{
5852 struct stream_in *in = (struct stream_in *)stream;
5853
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005854 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5855 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005856 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5857 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 -07005858 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5859 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305860 else if(audio_extn_cin_attached_usecase(in->usecase))
5861 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005862
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005863 return in->config.period_size * in->af_period_multiplier *
5864 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005865}
5866
5867static uint32_t in_get_channels(const struct audio_stream *stream)
5868{
5869 struct stream_in *in = (struct stream_in *)stream;
5870
5871 return in->channel_mask;
5872}
5873
5874static audio_format_t in_get_format(const struct audio_stream *stream)
5875{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005876 struct stream_in *in = (struct stream_in *)stream;
5877
5878 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005879}
5880
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005881static int in_set_format(struct audio_stream *stream __unused,
5882 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005883{
5884 return -ENOSYS;
5885}
5886
5887static int in_standby(struct audio_stream *stream)
5888{
5889 struct stream_in *in = (struct stream_in *)stream;
5890 struct audio_device *adev = in->dev;
5891 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305892 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5893 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005894 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305895
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005896 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005897 if (!in->standby && in->is_st_session) {
5898 ALOGD("%s: sound trigger pcm stop lab", __func__);
5899 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08005900 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005901 in->standby = 1;
5902 }
5903
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005904 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005905 if (adev->adm_deregister_stream)
5906 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
5907
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08005908 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005909 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08005910 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08005911 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08005912 voice_extn_compress_voip_close_input_stream(stream);
5913 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07005914 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
5915 do_stop = in->capture_started;
5916 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08005917 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305918 if (audio_extn_cin_attached_usecase(in->usecase))
5919 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08005920 }
5921
Arun Mirpuri5d170872019-03-26 13:21:31 -07005922 if (in->pcm) {
5923 ATRACE_BEGIN("pcm_in_close");
5924 pcm_close(in->pcm);
5925 ATRACE_END();
5926 in->pcm = NULL;
5927 }
5928
5929 if(do_stop) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005930 adev->enable_voicerx = false;
5931 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08005932 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005933 }
Quinn Malef6050362019-01-30 15:55:40 -08005934
5935 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
5936 adev->num_va_sessions--;
5937
Eric Laurent150dbfe2013-02-27 14:31:02 -08005938 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005939 }
5940 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07005941 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005942 return status;
5943}
5944
Aalique Grahame22e49102018-12-18 14:23:57 -08005945static int in_dump(const struct audio_stream *stream,
5946 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005947{
Aalique Grahame22e49102018-12-18 14:23:57 -08005948 struct stream_in *in = (struct stream_in *)stream;
5949
5950 // We try to get the lock for consistency,
5951 // but it isn't necessary for these variables.
5952 // If we're not in standby, we may be blocked on a read.
5953 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
5954 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
5955 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
5956 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
5957
5958 if (locked) {
5959 pthread_mutex_unlock(&in->lock);
5960 }
5961
5962 // dump error info
5963 (void)error_log_dump(
5964 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
5965
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005966 return 0;
5967}
5968
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305969static void in_snd_mon_cb(void * stream, struct str_parms * parms)
5970{
5971 if (!stream || !parms)
5972 return;
5973
5974 struct stream_in *in = (struct stream_in *)stream;
5975 struct audio_device *adev = in->dev;
5976
5977 card_status_t status;
5978 int card;
5979 if (parse_snd_card_status(parms, &card, &status) < 0)
5980 return;
5981
5982 pthread_mutex_lock(&adev->lock);
5983 bool valid_cb = (card == adev->snd_card);
5984 pthread_mutex_unlock(&adev->lock);
5985
5986 if (!valid_cb)
5987 return;
5988
5989 lock_input_stream(in);
5990 if (in->card_status != status)
5991 in->card_status = status;
5992 pthread_mutex_unlock(&in->lock);
5993
5994 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
5995 use_case_table[in->usecase],
5996 status == CARD_STATUS_OFFLINE ? "offline" : "online");
5997
5998 // a better solution would be to report error back to AF and let
5999 // it put the stream to standby
6000 if (status == CARD_STATUS_OFFLINE)
6001 in_standby(&in->stream.common);
6002
6003 return;
6004}
6005
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006006static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6007{
6008 struct stream_in *in = (struct stream_in *)stream;
6009 struct audio_device *adev = in->dev;
6010 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006011 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006012 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006013
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306014 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006015 parms = str_parms_create_str(kvpairs);
6016
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306017 if (!parms)
6018 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006019 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006020 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006021
6022 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6023 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006024 val = atoi(value);
6025 /* no audio source uses val == 0 */
6026 if ((in->source != val) && (val != 0)) {
6027 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006028 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6029 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6030 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006031 (in->config.rate == 8000 || in->config.rate == 16000 ||
6032 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006033 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006034 err = voice_extn_compress_voip_open_input_stream(in);
6035 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006036 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006037 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006038 }
6039 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006040 }
6041 }
6042
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006043 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6044 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006045 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006046 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6047
6048 // Workaround: If routing to an non existing usb device, fail gracefully
6049 // The routing request will otherwise block during 10 second
6050 int card;
6051 if (audio_is_usb_in_device(val) &&
6052 (card = get_alive_usb_card(parms)) >= 0) {
6053
6054 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6055 ret = -ENOSYS;
6056 } else {
6057
6058 in->device = val;
6059 /* If recording is in progress, change the tx device to new device */
6060 if (!in->standby && !in->is_st_session) {
6061 ALOGV("update input routing change");
6062 // inform adm before actual routing to prevent glitches.
6063 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006064 adev->adm_on_routing_change(adev->adm_data,
6065 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006066 ret = select_devices(adev, in->usecase);
6067 }
6068 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006069 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006070 }
6071 }
6072
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306073 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6074 if (err >= 0) {
6075 strlcpy(in->profile, value, sizeof(in->profile));
6076 ALOGV("updating stream profile with value '%s'", in->profile);
6077 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6078 &adev->streams_input_cfg_list,
6079 in->device, in->flags, in->format,
6080 in->sample_rate, in->bit_width,
6081 in->profile, &in->app_type_cfg);
6082 }
6083
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006084 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006085 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006086
6087 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306088error:
Eric Laurent994a6932013-07-17 11:51:42 -07006089 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006090 return ret;
6091}
6092
6093static char* in_get_parameters(const struct audio_stream *stream,
6094 const char *keys)
6095{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006096 struct stream_in *in = (struct stream_in *)stream;
6097 struct str_parms *query = str_parms_create_str(keys);
6098 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006099 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006100
6101 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006102 if (reply) {
6103 str_parms_destroy(reply);
6104 }
6105 if (query) {
6106 str_parms_destroy(query);
6107 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006108 ALOGE("in_get_parameters: failed to create query or reply");
6109 return NULL;
6110 }
6111
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006112 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006113
6114 voice_extn_in_get_parameters(in, query, reply);
6115
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006116 stream_get_parameter_channels(query, reply,
6117 &in->supported_channel_masks[0]);
6118 stream_get_parameter_formats(query, reply,
6119 &in->supported_formats[0]);
6120 stream_get_parameter_rates(query, reply,
6121 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006122 str = str_parms_to_str(reply);
6123 str_parms_destroy(query);
6124 str_parms_destroy(reply);
6125
6126 ALOGV("%s: exit: returns - %s", __func__, str);
6127 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006128}
6129
Aalique Grahame22e49102018-12-18 14:23:57 -08006130static int in_set_gain(struct audio_stream_in *stream,
6131 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006132{
Aalique Grahame22e49102018-12-18 14:23:57 -08006133 struct stream_in *in = (struct stream_in *)stream;
6134 char mixer_ctl_name[128];
6135 struct mixer_ctl *ctl;
6136 int ctl_value;
6137
6138 ALOGV("%s: gain %f", __func__, gain);
6139
6140 if (stream == NULL)
6141 return -EINVAL;
6142
6143 /* in_set_gain() only used to silence MMAP capture for now */
6144 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6145 return -ENOSYS;
6146
6147 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6148
6149 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6150 if (!ctl) {
6151 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6152 __func__, mixer_ctl_name);
6153 return -ENOSYS;
6154 }
6155
6156 if (gain < RECORD_GAIN_MIN)
6157 gain = RECORD_GAIN_MIN;
6158 else if (gain > RECORD_GAIN_MAX)
6159 gain = RECORD_GAIN_MAX;
6160 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6161
6162 mixer_ctl_set_value(ctl, 0, ctl_value);
6163
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006164 return 0;
6165}
6166
6167static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6168 size_t bytes)
6169{
6170 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306171
6172 if (in == NULL) {
6173 ALOGE("%s: stream_in ptr is NULL", __func__);
6174 return -EINVAL;
6175 }
6176
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006177 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306178 int ret = -1;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306179 size_t bytes_read = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006180
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006181 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306182
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006183 if (in->is_st_session) {
6184 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6185 /* Read from sound trigger HAL */
6186 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006187 if (in->standby) {
6188 adev->num_va_sessions++;
6189 in->standby = 0;
6190 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006191 pthread_mutex_unlock(&in->lock);
6192 return bytes;
6193 }
6194
Haynes Mathew George16081042017-05-31 17:16:49 -07006195 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6196 ret = -ENOSYS;
6197 goto exit;
6198 }
6199
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006200 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006201 pthread_mutex_lock(&adev->lock);
6202 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6203 ret = voice_extn_compress_voip_start_input_stream(in);
6204 else
6205 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006206 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6207 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006208 pthread_mutex_unlock(&adev->lock);
6209 if (ret != 0) {
6210 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006211 }
6212 in->standby = 0;
6213 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006214
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006215 // what's the duration requested by the client?
6216 long ns = 0;
6217
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306218 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006219 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6220 in->config.rate;
6221
6222 request_in_focus(in, ns);
6223 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006224
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306225 if (audio_extn_cin_attached_usecase(in->usecase)) {
6226 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6227 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306228 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006229 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306230 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006231 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006232 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006233 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006234 } else if (audio_extn_ffv_get_stream() == in) {
6235 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306236 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006237 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306238 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6239 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6240 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6241 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306242 ret = -EINVAL;
6243 goto exit;
6244 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306245 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306246 ret = -errno;
6247 }
6248 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306249 /* bytes read is always set to bytes for non compress usecases */
6250 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006251 }
6252
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006253 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006254
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006255 /*
Quinn Malef6050362019-01-30 15:55:40 -08006256 * Instead of writing zeroes here, we could trust the hardware to always
6257 * provide zeroes when muted. This is also muted with voice recognition
6258 * usecases so that other clients do not have access to voice recognition
6259 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006260 */
Quinn Malef6050362019-01-30 15:55:40 -08006261 if ((ret == 0 && voice_get_mic_mute(adev) &&
6262 !voice_is_in_call_rec_stream(in) &&
6263 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6264 (adev->num_va_sessions &&
6265 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6266 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6267 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006268 memset(buffer, 0, bytes);
6269
6270exit:
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006271 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306272 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006273 pthread_mutex_unlock(&in->lock);
6274
6275 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306276 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306277 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306278 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306279 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306280 in->standby = true;
6281 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306282 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6283 bytes_read = bytes;
6284 memset(buffer, 0, bytes);
6285 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006286 in_standby(&in->stream.common);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006287 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306288 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306289 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006290 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306291 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006292}
6293
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006294static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006295{
6296 return 0;
6297}
6298
Aalique Grahame22e49102018-12-18 14:23:57 -08006299static int in_get_capture_position(const struct audio_stream_in *stream,
6300 int64_t *frames, int64_t *time)
6301{
6302 if (stream == NULL || frames == NULL || time == NULL) {
6303 return -EINVAL;
6304 }
6305 struct stream_in *in = (struct stream_in *)stream;
6306 int ret = -ENOSYS;
6307
6308 lock_input_stream(in);
6309 // note: ST sessions do not close the alsa pcm driver synchronously
6310 // on standby. Therefore, we may return an error even though the
6311 // pcm stream is still opened.
6312 if (in->standby) {
6313 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6314 "%s stream in standby but pcm not NULL for non ST session", __func__);
6315 goto exit;
6316 }
6317 if (in->pcm) {
6318 struct timespec timestamp;
6319 unsigned int avail;
6320 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6321 *frames = in->frames_read + avail;
6322 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6323 ret = 0;
6324 }
6325 }
6326exit:
6327 pthread_mutex_unlock(&in->lock);
6328 return ret;
6329}
6330
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006331static int add_remove_audio_effect(const struct audio_stream *stream,
6332 effect_handle_t effect,
6333 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006334{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006335 struct stream_in *in = (struct stream_in *)stream;
6336 int status = 0;
6337 effect_descriptor_t desc;
6338
6339 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006340 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6341
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006342 if (status != 0)
6343 return status;
6344
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006345 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006346 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006347 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006348 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006349 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006350 in->enable_aec != enable &&
6351 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6352 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006353 if (!enable)
6354 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6355 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6356 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6357 in->dev->enable_voicerx = enable;
6358 struct audio_usecase *usecase;
6359 struct listnode *node;
6360 list_for_each(node, &in->dev->usecase_list) {
6361 usecase = node_to_item(node, struct audio_usecase, list);
6362 if (usecase->type == PCM_PLAYBACK)
6363 select_devices(in->dev, usecase->id);
6364 }
6365 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006366 if (!in->standby) {
6367 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6368 select_devices(in->dev, in->usecase);
6369 }
6370
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006371 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006372 if (in->enable_ns != enable &&
6373 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6374 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006375 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006376 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6377 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006378 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6379 select_devices(in->dev, in->usecase);
6380 } else
6381 select_devices(in->dev, in->usecase);
6382 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006383 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006384 pthread_mutex_unlock(&in->dev->lock);
6385 pthread_mutex_unlock(&in->lock);
6386
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006387 return 0;
6388}
6389
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006390static int in_add_audio_effect(const struct audio_stream *stream,
6391 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006392{
Eric Laurent994a6932013-07-17 11:51:42 -07006393 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006394 return add_remove_audio_effect(stream, effect, true);
6395}
6396
6397static int in_remove_audio_effect(const struct audio_stream *stream,
6398 effect_handle_t effect)
6399{
Eric Laurent994a6932013-07-17 11:51:42 -07006400 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006401 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006402}
6403
Derek Chenf939fb72018-11-13 13:34:41 -08006404streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6405 audio_io_handle_t input)
6406{
6407 struct listnode *node;
6408
6409 list_for_each(node, &dev->active_inputs_list) {
6410 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6411 streams_input_ctxt_t,
6412 list);
6413 if (in_ctxt->input->capture_handle == input) {
6414 return in_ctxt;
6415 }
6416 }
6417 return NULL;
6418}
6419
6420streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6421 audio_io_handle_t output)
6422{
6423 struct listnode *node;
6424
6425 list_for_each(node, &dev->active_outputs_list) {
6426 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6427 streams_output_ctxt_t,
6428 list);
6429 if (out_ctxt->output->handle == output) {
6430 return out_ctxt;
6431 }
6432 }
6433 return NULL;
6434}
6435
Haynes Mathew George16081042017-05-31 17:16:49 -07006436static int in_stop(const struct audio_stream_in* stream)
6437{
6438 struct stream_in *in = (struct stream_in *)stream;
6439 struct audio_device *adev = in->dev;
6440
6441 int ret = -ENOSYS;
6442 ALOGV("%s", __func__);
6443 pthread_mutex_lock(&adev->lock);
6444 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6445 in->capture_started && in->pcm != NULL) {
6446 pcm_stop(in->pcm);
6447 ret = stop_input_stream(in);
6448 in->capture_started = false;
6449 }
6450 pthread_mutex_unlock(&adev->lock);
6451 return ret;
6452}
6453
6454static int in_start(const struct audio_stream_in* stream)
6455{
6456 struct stream_in *in = (struct stream_in *)stream;
6457 struct audio_device *adev = in->dev;
6458 int ret = -ENOSYS;
6459
6460 ALOGV("%s in %p", __func__, in);
6461 pthread_mutex_lock(&adev->lock);
6462 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6463 !in->capture_started && in->pcm != NULL) {
6464 if (!in->capture_started) {
6465 ret = start_input_stream(in);
6466 if (ret == 0) {
6467 in->capture_started = true;
6468 }
6469 }
6470 }
6471 pthread_mutex_unlock(&adev->lock);
6472 return ret;
6473}
6474
6475static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6476 int32_t min_size_frames,
6477 struct audio_mmap_buffer_info *info)
6478{
6479 struct stream_in *in = (struct stream_in *)stream;
6480 struct audio_device *adev = in->dev;
6481 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006482 unsigned int offset1 = 0;
6483 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006484 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006485 uint32_t mmap_size = 0;
6486 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006487
6488 pthread_mutex_lock(&adev->lock);
6489 ALOGV("%s in %p", __func__, in);
6490
Sharad Sanglec6f32552018-05-04 16:15:38 +05306491 if (CARD_STATUS_OFFLINE == in->card_status||
6492 CARD_STATUS_OFFLINE == adev->card_status) {
6493 ALOGW("in->card_status or adev->card_status offline, try again");
6494 ret = -EIO;
6495 goto exit;
6496 }
6497
Haynes Mathew George16081042017-05-31 17:16:49 -07006498 if (info == NULL || min_size_frames == 0) {
6499 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6500 ret = -EINVAL;
6501 goto exit;
6502 }
6503 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6504 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6505 ALOGV("%s in %p", __func__, in);
6506 ret = -ENOSYS;
6507 goto exit;
6508 }
6509 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6510 if (in->pcm_device_id < 0) {
6511 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6512 __func__, in->pcm_device_id, in->usecase);
6513 ret = -EINVAL;
6514 goto exit;
6515 }
6516
6517 adjust_mmap_period_count(&in->config, min_size_frames);
6518
6519 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6520 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6521 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6522 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306523 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306524 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6525 in->card_status = CARD_STATUS_OFFLINE;
6526 adev->card_status = CARD_STATUS_OFFLINE;
6527 ret = -EIO;
6528 goto exit;
6529 }
6530
Haynes Mathew George16081042017-05-31 17:16:49 -07006531 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6532 step = "open";
6533 ret = -ENODEV;
6534 goto exit;
6535 }
6536
6537 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6538 if (ret < 0) {
6539 step = "begin";
6540 goto exit;
6541 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006542
Arun Mirpuri5d170872019-03-26 13:21:31 -07006543 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6544 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6545 info->burst_size_frames = in->config.period_size;
6546 ret = platform_get_mmap_data_fd(adev->platform,
6547 in->pcm_device_id, 1 /*capture*/,
6548 &info->shared_memory_fd,
6549 &mmap_size);
6550 if (ret < 0) {
6551 // Fall back to non exclusive mode
6552 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6553 } else {
6554 if (mmap_size < buffer_size) {
6555 step = "mmap";
6556 goto exit;
6557 }
6558 // FIXME: indicate exclusive mode support by returning a negative buffer size
6559 info->buffer_size_frames *= -1;
6560 }
6561
6562 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006563
6564 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6565 if (ret < 0) {
6566 step = "commit";
6567 goto exit;
6568 }
6569
6570 in->standby = false;
6571 ret = 0;
6572
6573 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6574 __func__, info->shared_memory_address, info->buffer_size_frames);
6575
6576exit:
6577 if (ret != 0) {
6578 if (in->pcm == NULL) {
6579 ALOGE("%s: %s - %d", __func__, step, ret);
6580 } else {
6581 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6582 pcm_close(in->pcm);
6583 in->pcm = NULL;
6584 }
6585 }
6586 pthread_mutex_unlock(&adev->lock);
6587 return ret;
6588}
6589
6590static int in_get_mmap_position(const struct audio_stream_in *stream,
6591 struct audio_mmap_position *position)
6592{
6593 struct stream_in *in = (struct stream_in *)stream;
6594 ALOGVV("%s", __func__);
6595 if (position == NULL) {
6596 return -EINVAL;
6597 }
6598 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6599 return -ENOSYS;
6600 }
6601 if (in->pcm == NULL) {
6602 return -ENOSYS;
6603 }
6604 struct timespec ts = { 0, 0 };
6605 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6606 if (ret < 0) {
6607 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6608 return ret;
6609 }
Naresh Tanniru119d74a2018-11-02 09:49:44 +05306610 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec;
Haynes Mathew George16081042017-05-31 17:16:49 -07006611 return 0;
6612}
6613
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306614static int in_get_active_microphones(const struct audio_stream_in *stream,
6615 struct audio_microphone_characteristic_t *mic_array,
6616 size_t *mic_count) {
6617 struct stream_in *in = (struct stream_in *)stream;
6618 struct audio_device *adev = in->dev;
6619 ALOGVV("%s", __func__);
6620
6621 lock_input_stream(in);
6622 pthread_mutex_lock(&adev->lock);
6623 int ret = platform_get_active_microphones(adev->platform,
6624 audio_channel_count_from_in_mask(in->channel_mask),
6625 in->usecase, mic_array, mic_count);
6626 pthread_mutex_unlock(&adev->lock);
6627 pthread_mutex_unlock(&in->lock);
6628
6629 return ret;
6630}
6631
6632static int adev_get_microphones(const struct audio_hw_device *dev,
6633 struct audio_microphone_characteristic_t *mic_array,
6634 size_t *mic_count) {
6635 struct audio_device *adev = (struct audio_device *)dev;
6636 ALOGVV("%s", __func__);
6637
6638 pthread_mutex_lock(&adev->lock);
6639 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6640 pthread_mutex_unlock(&adev->lock);
6641
6642 return ret;
6643}
juyuchendb308c22019-01-21 11:57:17 -07006644
6645static void in_update_sink_metadata(struct audio_stream_in *stream,
6646 const struct sink_metadata *sink_metadata) {
6647
6648 if (stream == NULL
6649 || sink_metadata == NULL
6650 || sink_metadata->tracks == NULL) {
6651 return;
6652 }
6653
6654 int error = 0;
6655 struct stream_in *in = (struct stream_in *)stream;
6656 struct audio_device *adev = in->dev;
6657 audio_devices_t device = AUDIO_DEVICE_NONE;
6658
6659 if (sink_metadata->track_count != 0)
6660 device = sink_metadata->tracks->dest_device;
6661
6662 lock_input_stream(in);
6663 pthread_mutex_lock(&adev->lock);
6664 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
6665
6666 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
6667 && device != AUDIO_DEVICE_NONE
6668 && adev->voice_tx_output != NULL) {
6669 /* Use the rx device from afe-proxy record to route voice call because
6670 there is no routing if tx device is on primary hal and rx device
6671 is on other hal during voice call. */
6672 adev->voice_tx_output->devices = device;
6673
6674 if (!voice_is_call_state_active(adev)) {
6675 if (adev->mode == AUDIO_MODE_IN_CALL) {
6676 adev->current_call_output = adev->voice_tx_output;
6677 error = voice_start_call(adev);
6678 if (error != 0)
6679 ALOGE("%s: start voice call failed %d", __func__, error);
6680 }
6681 } else {
6682 adev->current_call_output = adev->voice_tx_output;
6683 voice_update_devices_for_all_voice_usecases(adev);
6684 }
6685 }
6686
6687 pthread_mutex_unlock(&adev->lock);
6688 pthread_mutex_unlock(&in->lock);
6689}
6690
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306691int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006692 audio_io_handle_t handle,
6693 audio_devices_t devices,
6694 audio_output_flags_t flags,
6695 struct audio_config *config,
6696 struct audio_stream_out **stream_out,
6697 const char *address __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006698{
6699 struct audio_device *adev = (struct audio_device *)dev;
6700 struct stream_out *out;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306701 int ret = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006702 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006703 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306704 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006705 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6706 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6707 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6708 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006709 bool use_db_as_primary =
Aalique Grahame6e763712019-01-31 16:18:17 -08006710 audio_feature_manager_is_feature_enabled(USE_DEEP_BUFFER_AS_PRIMARY_OUTPUT);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006711 bool force_haptic_path =
6712 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07006713 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006714
kunleizdff872d2018-08-20 14:40:33 +08006715 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006716 is_usb_dev = false;
6717 devices = AUDIO_DEVICE_OUT_SPEAKER;
6718 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6719 __func__, devices);
6720 }
6721
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006722 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306723
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006724 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6725
Mingming Yin3a941d42016-02-17 18:08:05 -08006726 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
6727 stream_handle(%p)", __func__, config->format, config->sample_rate, config->channel_mask,
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306728 devices, flags, &out->stream);
6729
6730
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006731 if (!out) {
6732 return -ENOMEM;
6733 }
6734
Haynes Mathew George204045b2015-02-25 20:32:03 -08006735 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006736 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306737 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006738 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006739 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6740
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006741 if (devices == AUDIO_DEVICE_NONE)
6742 devices = AUDIO_DEVICE_OUT_SPEAKER;
6743
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006744 out->flags = flags;
6745 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006746 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006747 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006748 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306749 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306750 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6751 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6752 else
6753 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006754 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006755 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006756 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306757 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306758 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306759 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006760 out->hal_output_suspend_supported = 0;
6761 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306762 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306763 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306764 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006765
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306766 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306767 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006768 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6769
Aalique Grahame22e49102018-12-18 14:23:57 -08006770 if (direct_dev &&
6771 (audio_is_linear_pcm(out->format) ||
6772 config->format == AUDIO_FORMAT_DEFAULT) &&
6773 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6774 audio_format_t req_format = config->format;
6775 audio_channel_mask_t req_channel_mask = config->channel_mask;
6776 uint32_t req_sample_rate = config->sample_rate;
6777
6778 pthread_mutex_lock(&adev->lock);
6779 if (is_hdmi) {
6780 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6781 ret = read_hdmi_sink_caps(out);
6782 if (config->sample_rate == 0)
6783 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6784 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6785 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6786 if (config->format == AUDIO_FORMAT_DEFAULT)
6787 config->format = AUDIO_FORMAT_PCM_16_BIT;
6788 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006789 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6790 &config->format,
6791 &out->supported_formats[0],
6792 MAX_SUPPORTED_FORMATS,
6793 &config->channel_mask,
6794 &out->supported_channel_masks[0],
6795 MAX_SUPPORTED_CHANNEL_MASKS,
6796 &config->sample_rate,
6797 &out->supported_sample_rates[0],
6798 MAX_SUPPORTED_SAMPLE_RATES);
6799 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006800 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006801
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006802 pthread_mutex_unlock(&adev->lock);
6803 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006804 if (ret == -ENOSYS) {
6805 /* ignore and go with default */
6806 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006807 }
6808 // For MMAP NO IRQ, allow conversions in ADSP
6809 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6810 goto error_open;
6811 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006812 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006813 goto error_open;
6814 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006815
6816 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6817 config->sample_rate = req_sample_rate;
6818 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6819 config->channel_mask = req_channel_mask;
6820 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6821 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006822 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006823
6824 out->sample_rate = config->sample_rate;
6825 out->channel_mask = config->channel_mask;
6826 out->format = config->format;
6827 if (is_hdmi) {
6828 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6829 out->config = pcm_config_hdmi_multi;
6830 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6831 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6832 out->config = pcm_config_mmap_playback;
6833 out->stream.start = out_start;
6834 out->stream.stop = out_stop;
6835 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6836 out->stream.get_mmap_position = out_get_mmap_position;
6837 } else {
6838 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6839 out->config = pcm_config_hifi;
6840 }
6841
6842 out->config.rate = out->sample_rate;
6843 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6844 if (is_hdmi) {
6845 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6846 audio_bytes_per_sample(out->format));
6847 }
6848 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08006849 }
6850
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006851 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07006852 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006853 if (!voice_extn_is_compress_voip_supported()) {
6854 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
6855 out->sample_rate == 32000 || out->sample_rate == 48000) {
kunleizf6b5b082019-03-18 17:32:25 +08006856 out->channel_mask = AUDIO_CHANNEL_OUT_MONO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006857 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
6858 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07006859
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006860 out->config = default_pcm_config_voip_copp;
6861 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
6862 out->config.rate = out->sample_rate;
6863 }
6864 } else {
6865 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
6866 voice_extn_compress_voip_is_active(out->dev)) &&
6867 (voice_extn_compress_voip_is_config_supported(config))) {
6868 ret = voice_extn_compress_voip_open_output_stream(out);
6869 if (ret != 0) {
6870 ALOGE("%s: Compress voip output cannot be opened, error:%d",
6871 __func__, ret);
6872 goto error_open;
6873 }
6874 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006875 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006876 } else if (audio_is_linear_pcm(out->format) &&
6877 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
6878 out->channel_mask = config->channel_mask;
6879 out->sample_rate = config->sample_rate;
6880 out->format = config->format;
6881 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6882 // does this change?
6883 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
6884 out->config.rate = config->sample_rate;
6885 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6886 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6887 audio_bytes_per_sample(config->format));
6888 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07006889 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05306890 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306891 pthread_mutex_lock(&adev->lock);
6892 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
6893 pthread_mutex_unlock(&adev->lock);
6894
6895 // reject offload during card offline to allow
6896 // fallback to s/w paths
6897 if (offline) {
6898 ret = -ENODEV;
6899 goto error_open;
6900 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006901
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006902 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
6903 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
6904 ALOGE("%s: Unsupported Offload information", __func__);
6905 ret = -EINVAL;
6906 goto error_open;
6907 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006908
Atul Khare3fa6e542017-08-09 00:56:17 +05306909 if (config->offload_info.format == 0)
6910 config->offload_info.format = config->format;
6911 if (config->offload_info.sample_rate == 0)
6912 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07006913
Mingming Yin90310102013-11-13 16:57:00 -08006914 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306915 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07006916 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006917 ret = -EINVAL;
6918 goto error_open;
6919 }
6920
Ben Romberger0f8c87b2017-05-24 17:41:11 -07006921 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
6922 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
6923 (audio_extn_passthru_is_passthrough_stream(out)) &&
6924 !((config->sample_rate == 48000) ||
6925 (config->sample_rate == 96000) ||
6926 (config->sample_rate == 192000))) {
6927 ALOGE("%s: Unsupported sample rate %d for audio format %x",
6928 __func__, config->sample_rate, config->offload_info.format);
6929 ret = -EINVAL;
6930 goto error_open;
6931 }
6932
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006933 out->compr_config.codec = (struct snd_codec *)
6934 calloc(1, sizeof(struct snd_codec));
6935
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006936 if (!out->compr_config.codec) {
6937 ret = -ENOMEM;
6938 goto error_open;
6939 }
6940
Dhananjay Kumarac341582017-02-23 23:42:25 +05306941 out->stream.pause = out_pause;
6942 out->stream.resume = out_resume;
6943 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05306944 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306945 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07006946 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05306947 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07006948 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05306949 } else {
6950 out->usecase = get_offload_usecase(adev, false /* is_compress */);
6951 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07006952 }
vivek mehta446c3962015-09-14 10:57:35 -07006953
6954 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006955 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
6956 config->format == 0 && config->sample_rate == 0 &&
6957 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07006958 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08006959 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
6960 } else {
6961 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
6962 ret = -EEXIST;
6963 goto error_open;
6964 }
vivek mehta446c3962015-09-14 10:57:35 -07006965 }
6966
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006967 if (config->offload_info.channel_mask)
6968 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006969 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006970 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006971 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006972 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05306973 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006974 ret = -EINVAL;
6975 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08006976 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07006977
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006978 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006979 out->sample_rate = config->offload_info.sample_rate;
6980
Mingming Yin3ee55c62014-08-04 14:23:35 -07006981 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006982
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306983 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05306984 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05306985 audio_extn_dolby_send_ddp_endp_params(adev);
6986 audio_extn_dolby_set_dmid(adev);
6987 }
vivek mehta0ea887a2015-08-26 14:01:20 -07006988
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006989 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08006990 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006991 out->compr_config.codec->bit_rate =
6992 config->offload_info.bit_rate;
6993 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05306994 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006995 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05306996 /* Update bit width only for non passthrough usecases.
6997 * For passthrough usecases, the output will always be opened @16 bit
6998 */
6999 if (!audio_extn_passthru_is_passthrough_stream(out))
7000 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307001
7002 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7003 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7004 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7005
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007006 /*TODO: Do we need to change it for passthrough */
7007 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007008
Manish Dewangana6fc5442015-08-24 20:30:31 +05307009 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7010 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307011 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307012 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307013 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7014 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307015
7016 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7017 AUDIO_FORMAT_PCM) {
7018
7019 /*Based on platform support, configure appropriate alsa format for corresponding
7020 *hal input format.
7021 */
7022 out->compr_config.codec->format = hal_format_to_alsa(
7023 config->offload_info.format);
7024
Ashish Jain83a6cc22016-06-28 14:34:17 +05307025 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307026 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307027 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307028
Dhananjay Kumarac341582017-02-23 23:42:25 +05307029 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307030 *hal input format and alsa format might differ based on platform support.
7031 */
7032 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307033 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307034
7035 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7036
7037 /* Check if alsa session is configured with the same format as HAL input format,
7038 * if not then derive correct fragment size needed to accomodate the
7039 * conversion of HAL input format to alsa format.
7040 */
7041 audio_extn_utils_update_direct_pcm_fragment_size(out);
7042
7043 /*if hal input and output fragment size is different this indicates HAL input format is
7044 *not same as the alsa format
7045 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307046 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307047 /*Allocate a buffer to convert input data to the alsa configured format.
7048 *size of convert buffer is equal to the size required to hold one fragment size
7049 *worth of pcm data, this is because flinger does not write more than fragment_size
7050 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307051 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7052 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307053 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7054 ret = -ENOMEM;
7055 goto error_open;
7056 }
7057 }
7058 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7059 out->compr_config.fragment_size =
7060 audio_extn_passthru_get_buffer_size(&config->offload_info);
7061 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7062 } else {
7063 out->compr_config.fragment_size =
7064 platform_get_compress_offload_buffer_size(&config->offload_info);
7065 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7066 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007067
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307068 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7069 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7070 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007071 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307072 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007073
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307074 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7075 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7076 }
7077
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007078 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7079 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007080
Manish Dewangan69426c82017-01-30 17:35:36 +05307081 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7082 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7083 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7084 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7085 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7086 } else {
7087 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7088 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007089
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307090 memset(&out->channel_map_param, 0,
7091 sizeof(struct audio_out_channel_map_param));
7092
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007093 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307094 out->send_next_track_params = false;
7095 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007096 out->offload_state = OFFLOAD_STATE_IDLE;
7097 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007098 out->writeAt.tv_sec = 0;
7099 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007100
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007101 audio_extn_dts_create_state_notifier_node(out->usecase);
7102
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007103 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7104 __func__, config->offload_info.version,
7105 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307106
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307107 /* Check if DSD audio format is supported in codec
7108 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307109 */
7110
7111 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307112 (!platform_check_codec_dsd_support(adev->platform) ||
7113 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307114 ret = -EINVAL;
7115 goto error_open;
7116 }
7117
Ashish Jain5106d362016-05-11 19:23:33 +05307118 /* Disable gapless if any of the following is true
7119 * passthrough playback
7120 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307121 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307122 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307123 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307124 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007125 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307126 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307127 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307128 check_and_set_gapless_mode(adev, false);
7129 } else
7130 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007131
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307132 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007133 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7134 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307135 if (config->format == AUDIO_FORMAT_DSD) {
7136 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7137 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7138 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007139
7140 create_offload_callback_thread(out);
7141
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007142 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007143 switch (config->sample_rate) {
7144 case 0:
7145 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7146 break;
7147 case 8000:
7148 case 16000:
7149 case 48000:
7150 out->sample_rate = config->sample_rate;
7151 break;
7152 default:
7153 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7154 config->sample_rate);
7155 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7156 ret = -EINVAL;
7157 goto error_open;
7158 }
7159 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7160 switch (config->channel_mask) {
7161 case AUDIO_CHANNEL_NONE:
7162 case AUDIO_CHANNEL_OUT_STEREO:
7163 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7164 break;
7165 default:
7166 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7167 config->channel_mask);
7168 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7169 ret = -EINVAL;
7170 goto error_open;
7171 }
7172 switch (config->format) {
7173 case AUDIO_FORMAT_DEFAULT:
7174 case AUDIO_FORMAT_PCM_16_BIT:
7175 out->format = AUDIO_FORMAT_PCM_16_BIT;
7176 break;
7177 default:
7178 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7179 config->format);
7180 config->format = AUDIO_FORMAT_PCM_16_BIT;
7181 ret = -EINVAL;
7182 goto error_open;
7183 }
7184
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307185 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007186 if (ret != 0) {
7187 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007188 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007189 goto error_open;
7190 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007191 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007192 switch (config->sample_rate) {
7193 case 0:
7194 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7195 break;
7196 case 8000:
7197 case 16000:
7198 case 48000:
7199 out->sample_rate = config->sample_rate;
7200 break;
7201 default:
7202 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7203 config->sample_rate);
7204 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7205 ret = -EINVAL;
7206 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007207 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007208 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7209 switch (config->channel_mask) {
7210 case AUDIO_CHANNEL_NONE:
7211 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7212 break;
7213 case AUDIO_CHANNEL_OUT_STEREO:
7214 out->channel_mask = config->channel_mask;
7215 break;
7216 default:
7217 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7218 config->channel_mask);
7219 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7220 ret = -EINVAL;
7221 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007222 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007223 switch (config->format) {
7224 case AUDIO_FORMAT_DEFAULT:
7225 out->format = AUDIO_FORMAT_PCM_16_BIT;
7226 break;
7227 case AUDIO_FORMAT_PCM_16_BIT:
7228 out->format = config->format;
7229 break;
7230 default:
7231 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7232 config->format);
7233 config->format = AUDIO_FORMAT_PCM_16_BIT;
7234 ret = -EINVAL;
7235 break;
7236 }
7237 if (ret != 0)
7238 goto error_open;
7239
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007240 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7241 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007242 out->config.rate = out->sample_rate;
7243 out->config.channels =
7244 audio_channel_count_from_out_mask(out->channel_mask);
7245 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007246 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007247 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307248 unsigned int channels = 0;
7249 /*Update config params to default if not set by the caller*/
7250 if (config->sample_rate == 0)
7251 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7252 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7253 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7254 if (config->format == AUDIO_FORMAT_DEFAULT)
7255 config->format = AUDIO_FORMAT_PCM_16_BIT;
7256
7257 channels = audio_channel_count_from_out_mask(out->channel_mask);
7258
Varun Balaraje49253e2017-07-06 19:48:56 +05307259 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7260 out->usecase = get_interactive_usecase(adev);
7261 out->config = pcm_config_low_latency;
7262 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307263 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007264 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7265 out->flags);
7266 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007267 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7268 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7269 out->config = pcm_config_mmap_playback;
7270 out->stream.start = out_start;
7271 out->stream.stop = out_stop;
7272 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7273 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307274 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7275 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007276 out->hal_output_suspend_supported =
7277 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7278 out->dynamic_pm_qos_config_supported =
7279 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7280 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007281 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7282 } else {
7283 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7284 //the mixer path will be a string similar to "low-latency-playback resume"
7285 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7286 strlcat(out->pm_qos_mixer_path,
7287 " resume", MAX_MIXER_PATH_LEN);
7288 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7289 out->pm_qos_mixer_path);
7290 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307291 out->config = pcm_config_low_latency;
7292 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7293 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7294 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307295 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7296 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7297 if (out->config.period_size <= 0) {
7298 ALOGE("Invalid configuration period size is not valid");
7299 ret = -EINVAL;
7300 goto error_open;
7301 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007302 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7303 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7304 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007305 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7306 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7307 out->config = pcm_config_haptics_audio;
7308 if (force_haptic_path)
7309 adev->haptics_config = pcm_config_haptics_audio;
7310 else
7311 adev->haptics_config = pcm_config_haptics;
7312
7313 out->config.channels =
7314 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7315
7316 if (force_haptic_path) {
7317 out->config.channels = 1;
7318 adev->haptics_config.channels = 1;
7319 } else
7320 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307321 } else {
7322 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007323 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7324 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307325 }
7326 out->hal_ip_format = format = out->format;
7327 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7328 out->hal_op_format = pcm_format_to_hal(out->config.format);
7329 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7330 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007331 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307332 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307333 if (out->hal_ip_format != out->hal_op_format) {
7334 uint32_t buffer_size = out->config.period_size *
7335 format_to_bitwidth_table[out->hal_op_format] *
7336 out->config.channels;
7337 out->convert_buffer = calloc(1, buffer_size);
7338 if (out->convert_buffer == NULL){
7339 ALOGE("Allocation failed for convert buffer for size %d",
7340 out->compr_config.fragment_size);
7341 ret = -ENOMEM;
7342 goto error_open;
7343 }
7344 ALOGD("Convert buffer allocated of size %d", buffer_size);
7345 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007346 }
7347
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007348 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7349 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307350
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007351 /* TODO remove this hardcoding and check why width is zero*/
7352 if (out->bit_width == 0)
7353 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307354 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007355 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007356 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307357 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307358 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007359 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007360 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7361 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007362 if(adev->primary_output == NULL)
7363 adev->primary_output = out;
7364 else {
7365 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007366 ret = -EEXIST;
7367 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007368 }
7369 }
7370
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007371 /* Check if this usecase is already existing */
7372 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007373 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7374 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007375 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007376 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007377 ret = -EEXIST;
7378 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007379 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007380
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007381 pthread_mutex_unlock(&adev->lock);
7382
7383 out->stream.common.get_sample_rate = out_get_sample_rate;
7384 out->stream.common.set_sample_rate = out_set_sample_rate;
7385 out->stream.common.get_buffer_size = out_get_buffer_size;
7386 out->stream.common.get_channels = out_get_channels;
7387 out->stream.common.get_format = out_get_format;
7388 out->stream.common.set_format = out_set_format;
7389 out->stream.common.standby = out_standby;
7390 out->stream.common.dump = out_dump;
7391 out->stream.common.set_parameters = out_set_parameters;
7392 out->stream.common.get_parameters = out_get_parameters;
7393 out->stream.common.add_audio_effect = out_add_audio_effect;
7394 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7395 out->stream.get_latency = out_get_latency;
7396 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007397#ifdef NO_AUDIO_OUT
7398 out->stream.write = out_write_for_no_output;
7399#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007400 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007401#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007402 out->stream.get_render_position = out_get_render_position;
7403 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007404 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007405
Haynes Mathew George16081042017-05-31 17:16:49 -07007406 if (out->realtime)
7407 out->af_period_multiplier = af_period_multiplier;
7408 else
7409 out->af_period_multiplier = 1;
7410
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007411 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007412 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007413 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007414
7415 config->format = out->stream.common.get_format(&out->stream.common);
7416 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7417 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307418 register_format(out->format, out->supported_formats);
7419 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7420 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007421
Aalique Grahame22e49102018-12-18 14:23:57 -08007422 out->error_log = error_log_create(
7423 ERROR_LOG_ENTRIES,
7424 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7425
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307426 /*
7427 By locking output stream before registering, we allow the callback
7428 to update stream's state only after stream's initial state is set to
7429 adev state.
7430 */
7431 lock_output_stream(out);
7432 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7433 pthread_mutex_lock(&adev->lock);
7434 out->card_status = adev->card_status;
7435 pthread_mutex_unlock(&adev->lock);
7436 pthread_mutex_unlock(&out->lock);
7437
Aalique Grahame22e49102018-12-18 14:23:57 -08007438 stream_app_type_cfg_init(&out->app_type_cfg);
7439
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007440 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307441 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007442 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007443
7444 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7445 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7446 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007447 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307448 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007449 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007450 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Manish Dewangan21a850a2017-08-14 12:03:55 +05307451 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007452 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7453 out->usecase, PCM_PLAYBACK);
7454 hdlr_stream_cfg.flags = out->flags;
7455 hdlr_stream_cfg.type = PCM_PLAYBACK;
7456 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7457 &hdlr_stream_cfg);
7458 if (ret) {
7459 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7460 out->adsp_hdlr_stream_handle = NULL;
7461 }
7462 }
Manish Dewangan21a850a2017-08-14 12:03:55 +05307463 if (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false)) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007464 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007465 if (ret < 0) {
7466 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7467 out->ip_hdlr_handle = NULL;
7468 }
7469 }
Derek Chenf939fb72018-11-13 13:34:41 -08007470
7471 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7472 calloc(1, sizeof(streams_output_ctxt_t));
7473 if (out_ctxt == NULL) {
7474 ALOGE("%s fail to allocate output ctxt", __func__);
7475 ret = -ENOMEM;
7476 goto error_open;
7477 }
7478 out_ctxt->output = out;
7479
7480 pthread_mutex_lock(&adev->lock);
7481 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7482 pthread_mutex_unlock(&adev->lock);
7483
Eric Laurent994a6932013-07-17 11:51:42 -07007484 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007485 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007486
7487error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307488 if (out->convert_buffer)
7489 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007490 free(out);
7491 *stream_out = NULL;
7492 ALOGD("%s: exit: ret %d", __func__, ret);
7493 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007494}
7495
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307496void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007497 struct audio_stream_out *stream)
7498{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007499 struct stream_out *out = (struct stream_out *)stream;
7500 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007501 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007502
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007503 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307504
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307505 // must deregister from sndmonitor first to prevent races
7506 // between the callback and close_stream
7507 audio_extn_snd_mon_unregister_listener(out);
7508
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007509 /* close adsp hdrl session before standby */
7510 if (out->adsp_hdlr_stream_handle) {
7511 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7512 if (ret)
7513 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7514 out->adsp_hdlr_stream_handle = NULL;
7515 }
7516
Manish Dewangan21a850a2017-08-14 12:03:55 +05307517 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007518 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7519 out->ip_hdlr_handle = NULL;
7520 }
7521
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007522 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307523 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007524 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307525 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307526 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007527 if(ret != 0)
7528 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7529 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007530 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007531 out_standby(&stream->common);
7532
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007533 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007534 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007535 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007536 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007537 if (out->compr_config.codec != NULL)
7538 free(out->compr_config.codec);
7539 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007540
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307541 out->a2dp_compress_mute = false;
7542
Varun Balaraje49253e2017-07-06 19:48:56 +05307543 if (is_interactive_usecase(out->usecase))
7544 free_interactive_usecase(adev, out->usecase);
7545
Ashish Jain83a6cc22016-06-28 14:34:17 +05307546 if (out->convert_buffer != NULL) {
7547 free(out->convert_buffer);
7548 out->convert_buffer = NULL;
7549 }
7550
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007551 if (adev->voice_tx_output == out)
7552 adev->voice_tx_output = NULL;
7553
Aalique Grahame22e49102018-12-18 14:23:57 -08007554 error_log_destroy(out->error_log);
7555 out->error_log = NULL;
7556
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307557 if (adev->primary_output == out)
7558 adev->primary_output = NULL;
7559
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007560 pthread_cond_destroy(&out->cond);
7561 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007562
7563 pthread_mutex_lock(&adev->lock);
7564 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7565 if (out_ctxt != NULL) {
7566 list_remove(&out_ctxt->list);
7567 free(out_ctxt);
7568 } else {
7569 ALOGW("%s, output stream already closed", __func__);
7570 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007571 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007572 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007573 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007574}
7575
7576static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7577{
7578 struct audio_device *adev = (struct audio_device *)dev;
7579 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007580 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007581 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007582 int ret;
7583 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007584 bool a2dp_reconfig = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007585
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007586 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007587 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007588
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307589 if (!parms)
7590 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307591
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307592 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7593 if (ret >= 0) {
7594 /* When set to false, HAL should disable EC and NS */
7595 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7596 adev->bt_sco_on = true;
7597 else
7598 adev->bt_sco_on = false;
7599 }
7600
Naresh Tanniru4c630392014-05-12 01:05:52 +05307601 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007602 status = voice_set_parameters(adev, parms);
7603 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007604 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007605
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007606 status = platform_set_parameters(adev->platform, parms);
7607 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007608 goto done;
7609
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007610 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7611 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007612 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007613 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7614 adev->bluetooth_nrec = true;
7615 else
7616 adev->bluetooth_nrec = false;
7617 }
7618
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007619 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7620 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007621 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7622 adev->screen_off = false;
7623 else
7624 adev->screen_off = true;
7625 }
7626
Aalique Grahame22e49102018-12-18 14:23:57 -08007627#ifndef MAXXAUDIO_QDSP_ENABLED
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007628 ret = str_parms_get_int(parms, "rotation", &val);
7629 if (ret >= 0) {
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007630 bool reverse_speakers = false;
7631 switch(val) {
7632 // FIXME: note that the code below assumes that the speakers are in the correct placement
7633 // relative to the user when the device is rotated 90deg from its default rotation. This
7634 // assumption is device-specific, not platform-specific like this code.
7635 case 270:
7636 reverse_speakers = true;
7637 break;
7638 case 0:
7639 case 90:
7640 case 180:
7641 break;
7642 default:
7643 ALOGE("%s: unexpected rotation of %d", __func__, val);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007644 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007645 }
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007646 if (status == 0) {
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07007647 // check and set swap
7648 // - check if orientation changed and speaker active
7649 // - set rotation and cache the rotation value
7650 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007651 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007652 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007653#endif
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007654
Mingming Yin514a8bc2014-07-29 15:22:21 -07007655 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7656 if (ret >= 0) {
7657 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7658 adev->bt_wb_speech_enabled = true;
7659 else
7660 adev->bt_wb_speech_enabled = false;
7661 }
7662
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007663 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7664 if (ret >= 0) {
7665 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307666 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007667 if (audio_is_output_device(val) &&
7668 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007669 ALOGV("cache new ext disp type and edid");
7670 ret = platform_get_ext_disp_type(adev->platform);
7671 if (ret < 0) {
7672 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307673 } else {
7674 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007675 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307676 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007677 /*
7678 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7679 * Per AudioPolicyManager, USB device is higher priority than WFD.
7680 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7681 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7682 * starting voice call on USB
7683 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007684 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307685 if (ret >= 0)
7686 audio_extn_usb_add_device(device, atoi(value));
7687
Zhou Song6f862822017-11-06 17:27:57 +08007688 if (!audio_extn_usb_is_tunnel_supported()) {
7689 ALOGV("detected USB connect .. disable proxy");
7690 adev->allow_afe_proxy_usage = false;
7691 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007692 }
7693 }
7694
7695 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7696 if (ret >= 0) {
7697 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307698 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007699 /*
7700 * The HDMI / Displayport disconnect handling has been moved to
7701 * audio extension to ensure that its parameters are not
7702 * invalidated prior to updating sysfs of the disconnect event
7703 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7704 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307705 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007706 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307707 if (ret >= 0)
7708 audio_extn_usb_remove_device(device, atoi(value));
7709
Zhou Song6f862822017-11-06 17:27:57 +08007710 if (!audio_extn_usb_is_tunnel_supported()) {
7711 ALOGV("detected USB disconnect .. enable proxy");
7712 adev->allow_afe_proxy_usage = true;
7713 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007714 }
7715 }
7716
Aalique Grahame22e49102018-12-18 14:23:57 -08007717 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007718 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007719
7720 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007721 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307722 struct audio_usecase *usecase;
7723 struct listnode *node;
7724 list_for_each(node, &adev->usecase_list) {
7725 usecase = node_to_item(node, struct audio_usecase, list);
7726 if ((usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007727 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307728 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007729
7730 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307731 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007732 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307733 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307734 //force device switch to re configure encoder
7735 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307736 audio_extn_a2dp_set_handoff_mode(false);
7737 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307738 break;
7739 }
7740 }
7741 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007742
7743 //handle vr audio setparam
7744 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7745 value, sizeof(value));
7746 if (ret >= 0) {
7747 ALOGI("Setting vr mode to be %s", value);
7748 if (!strncmp(value, "true", 4)) {
7749 adev->vr_audio_mode_enabled = true;
7750 ALOGI("Setting vr mode to true");
7751 } else if (!strncmp(value, "false", 5)) {
7752 adev->vr_audio_mode_enabled = false;
7753 ALOGI("Setting vr mode to false");
7754 } else {
7755 ALOGI("wrong vr mode set");
7756 }
7757 }
7758
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307759 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007760done:
7761 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007762 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307763error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007764 ALOGV("%s: exit with code(%d)", __func__, status);
7765 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007766}
7767
7768static char* adev_get_parameters(const struct audio_hw_device *dev,
7769 const char *keys)
7770{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307771 ALOGD("%s:%s", __func__, keys);
7772
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007773 struct audio_device *adev = (struct audio_device *)dev;
7774 struct str_parms *reply = str_parms_create();
7775 struct str_parms *query = str_parms_create_str(keys);
7776 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307777 char value[256] = {0};
7778 int ret = 0;
7779
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007780 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007781 if (reply) {
7782 str_parms_destroy(reply);
7783 }
7784 if (query) {
7785 str_parms_destroy(query);
7786 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007787 ALOGE("adev_get_parameters: failed to create query or reply");
7788 return NULL;
7789 }
7790
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007791 //handle vr audio getparam
7792
7793 ret = str_parms_get_str(query,
7794 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7795 value, sizeof(value));
7796
7797 if (ret >= 0) {
7798 bool vr_audio_enabled = false;
7799 pthread_mutex_lock(&adev->lock);
7800 vr_audio_enabled = adev->vr_audio_mode_enabled;
7801 pthread_mutex_unlock(&adev->lock);
7802
7803 ALOGI("getting vr mode to %d", vr_audio_enabled);
7804
7805 if (vr_audio_enabled) {
7806 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7807 "true");
7808 goto exit;
7809 } else {
7810 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7811 "false");
7812 goto exit;
7813 }
7814 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007815
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007816 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007817 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08007818 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08007819 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007820 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05307821 pthread_mutex_unlock(&adev->lock);
7822
Naresh Tannirud7205b62014-06-20 02:54:48 +05307823exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007824 str = str_parms_to_str(reply);
7825 str_parms_destroy(query);
7826 str_parms_destroy(reply);
7827
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307828 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007829 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007830}
7831
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007832static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007833{
7834 return 0;
7835}
7836
7837static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
7838{
Haynes Mathew George5191a852013-09-11 14:19:36 -07007839 int ret;
7840 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08007841
7842 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
7843
Haynes Mathew George5191a852013-09-11 14:19:36 -07007844 pthread_mutex_lock(&adev->lock);
7845 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07007846 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07007847 pthread_mutex_unlock(&adev->lock);
7848 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007849}
7850
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007851static int adev_set_master_volume(struct audio_hw_device *dev __unused,
7852 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007853{
7854 return -ENOSYS;
7855}
7856
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007857static int adev_get_master_volume(struct audio_hw_device *dev __unused,
7858 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007859{
7860 return -ENOSYS;
7861}
7862
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007863static int adev_set_master_mute(struct audio_hw_device *dev __unused,
7864 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007865{
7866 return -ENOSYS;
7867}
7868
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007869static int adev_get_master_mute(struct audio_hw_device *dev __unused,
7870 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007871{
7872 return -ENOSYS;
7873}
7874
7875static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
7876{
7877 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07007878 struct listnode *node;
7879 struct audio_usecase *usecase = NULL;
7880 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08007881
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007882 pthread_mutex_lock(&adev->lock);
7883 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007884 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007885 adev->mode = mode;
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08007886 if ((mode == AUDIO_MODE_NORMAL) && voice_is_in_call(adev)) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07007887 list_for_each(node, &adev->usecase_list) {
7888 usecase = node_to_item(node, struct audio_usecase, list);
7889 if (usecase->type == VOICE_CALL)
7890 break;
7891 }
7892 if (usecase &&
7893 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
7894 ret = audio_extn_usb_check_and_set_svc_int(usecase,
7895 true);
7896 if (ret != 0) {
7897 /* default service interval was successfully updated,
7898 reopen USB backend with new service interval */
7899 check_usecases_codec_backend(adev,
7900 usecase,
7901 usecase->out_snd_device);
7902 }
7903 }
7904
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007905 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07007906 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007907 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08007908 // restore device for other active usecases after stop call
7909 list_for_each(node, &adev->usecase_list) {
7910 usecase = node_to_item(node, struct audio_usecase, list);
7911 select_devices(adev, usecase->id);
7912 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007913 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007914 }
7915 pthread_mutex_unlock(&adev->lock);
7916 return 0;
7917}
7918
7919static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
7920{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007921 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08007922 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007923
7924 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08007925 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007926 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007927
Derek Chend2530072014-11-24 12:39:14 -08007928 if (adev->ext_hw_plugin)
7929 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08007930
7931 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007932 pthread_mutex_unlock(&adev->lock);
7933
7934 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007935}
7936
7937static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
7938{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007939 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007940 return 0;
7941}
7942
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07007943static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007944 const struct audio_config *config)
7945{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007946 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007947
Aalique Grahame22e49102018-12-18 14:23:57 -08007948 /* Don't know if USB HIFI in this context so use true to be conservative */
7949 if (check_input_parameters(config->sample_rate, config->format, channel_count,
7950 true /*is_usb_hifi */) != 0)
7951 return 0;
7952
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07007953 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
7954 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007955}
7956
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007957static bool adev_input_allow_hifi_record(struct audio_device *adev,
7958 audio_devices_t devices,
7959 audio_input_flags_t flags,
7960 audio_source_t source) {
7961 const bool allowed = true;
7962
7963 if (!audio_is_usb_in_device(devices))
7964 return !allowed;
7965
7966 switch (flags) {
7967 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007968 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07007969 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
7970 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007971 default:
7972 return !allowed;
7973 }
7974
7975 switch (source) {
7976 case AUDIO_SOURCE_DEFAULT:
7977 case AUDIO_SOURCE_MIC:
7978 case AUDIO_SOURCE_UNPROCESSED:
7979 break;
7980 default:
7981 return !allowed;
7982 }
7983
7984 switch (adev->mode) {
7985 case 0:
7986 break;
7987 default:
7988 return !allowed;
7989 }
7990
7991 return allowed;
7992}
7993
Haynes Mathew George4ffef292017-11-21 15:08:02 -08007994static int adev_update_voice_comm_input_stream(struct stream_in *in,
7995 struct audio_config *config)
7996{
7997 bool valid_rate = (config->sample_rate == 8000 ||
7998 config->sample_rate == 16000 ||
7999 config->sample_rate == 32000 ||
8000 config->sample_rate == 48000);
8001 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8002
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008003 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008004 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008005 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8006 in->config = default_pcm_config_voip_copp;
8007 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8008 DEFAULT_VOIP_BUF_DURATION_MS,
8009 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008010 } else {
8011 ALOGW("%s No valid input in voip, use defaults"
8012 "sample rate %u, channel mask 0x%X",
8013 __func__, config->sample_rate, in->channel_mask);
8014 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008015 in->config.rate = config->sample_rate;
8016 in->sample_rate = config->sample_rate;
8017 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008018 //XXX needed for voice_extn_compress_voip_open_input_stream
8019 in->config.rate = config->sample_rate;
8020 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8021 voice_extn_compress_voip_is_active(in->dev)) &&
8022 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8023 valid_rate && valid_ch) {
8024 voice_extn_compress_voip_open_input_stream(in);
8025 // update rate entries to match config from AF
8026 in->config.rate = config->sample_rate;
8027 in->sample_rate = config->sample_rate;
8028 } else {
8029 ALOGW("%s compress voip not active, use defaults", __func__);
8030 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008031 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008032 return 0;
8033}
8034
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008035static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008036 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008037 audio_devices_t devices,
8038 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008039 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308040 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008041 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008042 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008043{
8044 struct audio_device *adev = (struct audio_device *)dev;
8045 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008046 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008047 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008048 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308049 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008050 bool is_usb_dev = audio_is_usb_in_device(devices);
8051 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8052 devices,
8053 flags,
8054 source);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308055
kunleizdff872d2018-08-20 14:40:33 +08008056 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008057 is_usb_dev = false;
8058 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8059 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8060 __func__, devices);
8061 }
8062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008063 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008064
8065 if (!(is_usb_dev && may_use_hifi_record)) {
8066 if (config->sample_rate == 0)
8067 config->sample_rate = 48000;
8068 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8069 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8070 if (config->format == AUDIO_FORMAT_DEFAULT)
8071 config->format = AUDIO_FORMAT_PCM_16_BIT;
8072
8073 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8074
Aalique Grahame22e49102018-12-18 14:23:57 -08008075 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8076 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008077 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308078 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008079
8080 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008081
8082 if (!in) {
8083 ALOGE("failed to allocate input stream");
8084 return -ENOMEM;
8085 }
8086
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308087 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308088 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8089 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008090 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008091 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008092
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008093 in->stream.common.get_sample_rate = in_get_sample_rate;
8094 in->stream.common.set_sample_rate = in_set_sample_rate;
8095 in->stream.common.get_buffer_size = in_get_buffer_size;
8096 in->stream.common.get_channels = in_get_channels;
8097 in->stream.common.get_format = in_get_format;
8098 in->stream.common.set_format = in_set_format;
8099 in->stream.common.standby = in_standby;
8100 in->stream.common.dump = in_dump;
8101 in->stream.common.set_parameters = in_set_parameters;
8102 in->stream.common.get_parameters = in_get_parameters;
8103 in->stream.common.add_audio_effect = in_add_audio_effect;
8104 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8105 in->stream.set_gain = in_set_gain;
8106 in->stream.read = in_read;
8107 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008108 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308109 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008110 in->stream.set_microphone_direction = in_set_microphone_direction;
8111 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008112 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008113
8114 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008115 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008116 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008117 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008118 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008119 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008120 in->bit_width = 16;
8121 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008122 in->direction = MIC_DIRECTION_UNSPECIFIED;
8123 in->zoom = 0;
Haynes Mathew George46740472017-10-27 18:40:12 -07008124
Aalique Grahame22e49102018-12-18 14:23:57 -08008125 ALOGV("%s: source = %d, config->channel_mask = %d", __func__, source, config->channel_mask);
8126 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8127 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8128 /* Force channel config requested to mono if incall
8129 record is being requested for only uplink/downlink */
8130 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8131 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8132 ret = -EINVAL;
8133 goto err_open;
8134 }
8135 }
8136
Haynes Mathew George46740472017-10-27 18:40:12 -07008137 /* Update config params with the requested sample rate and channels */
8138 if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) &&
8139 (adev->mode != AUDIO_MODE_IN_CALL)) {
8140 ret = -EINVAL;
8141 goto err_open;
8142 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008143
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008144 if (is_usb_dev && may_use_hifi_record) {
8145 /* HiFi record selects an appropriate format, channel, rate combo
8146 depending on sink capabilities*/
8147 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8148 &config->format,
8149 &in->supported_formats[0],
8150 MAX_SUPPORTED_FORMATS,
8151 &config->channel_mask,
8152 &in->supported_channel_masks[0],
8153 MAX_SUPPORTED_CHANNEL_MASKS,
8154 &config->sample_rate,
8155 &in->supported_sample_rates[0],
8156 MAX_SUPPORTED_SAMPLE_RATES);
8157 if (ret != 0) {
8158 ret = -EINVAL;
8159 goto err_open;
8160 }
8161 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008162 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308163 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308164 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8165 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8166 in->config.format = PCM_FORMAT_S32_LE;
8167 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308168 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8169 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8170 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8171 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8172 bool ret_error = false;
8173 in->bit_width = 24;
8174 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8175 from HAL is 24_packed and 8_24
8176 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8177 24_packed return error indicating supported format is 24_packed
8178 *> In case of any other source requesting 24 bit or float return error
8179 indicating format supported is 16 bit only.
8180
8181 on error flinger will retry with supported format passed
8182 */
8183 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8184 (source != AUDIO_SOURCE_CAMCORDER)) {
8185 config->format = AUDIO_FORMAT_PCM_16_BIT;
8186 if (config->sample_rate > 48000)
8187 config->sample_rate = 48000;
8188 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008189 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8190 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308191 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8192 ret_error = true;
8193 }
8194
8195 if (ret_error) {
8196 ret = -EINVAL;
8197 goto err_open;
8198 }
8199 }
8200
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008201 in->channel_mask = config->channel_mask;
8202 in->format = config->format;
8203
8204 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308205
8206 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8207 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8208 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8209 else {
8210 ret = -EINVAL;
8211 goto err_open;
8212 }
8213 }
8214
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008215 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8216 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8217 is_low_latency = true;
8218#if LOW_LATENCY_CAPTURE_USE_CASE
8219 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8220#endif
8221 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008222 if (!in->realtime) {
8223 in->config = pcm_config_audio_capture;
8224 frame_size = audio_stream_in_frame_size(&in->stream);
8225 buffer_size = get_input_buffer_size(config->sample_rate,
8226 config->format,
8227 channel_count,
8228 is_low_latency);
8229 in->config.period_size = buffer_size / frame_size;
8230 in->config.rate = config->sample_rate;
8231 in->af_period_multiplier = 1;
8232 } else {
8233 // period size is left untouched for rt mode playback
8234 in->config = pcm_config_audio_capture_rt;
8235 in->af_period_multiplier = af_period_multiplier;
8236 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008237 }
8238
8239 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8240 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8241 in->realtime = 0;
8242 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8243 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008244 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008245 in->stream.start = in_start;
8246 in->stream.stop = in_stop;
8247 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8248 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008249 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8250 } else if (in->realtime) {
8251 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008252 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008253 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008254 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008255 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8256 in->config = pcm_config_audio_capture;
8257 frame_size = audio_stream_in_frame_size(&in->stream);
8258 buffer_size = get_input_buffer_size(config->sample_rate,
8259 config->format,
8260 channel_count,
8261 false /*is_low_latency*/);
8262 in->config.period_size = buffer_size / frame_size;
8263 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008264 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008265 switch (config->format) {
8266 case AUDIO_FORMAT_PCM_32_BIT:
8267 in->bit_width = 32;
8268 break;
8269 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8270 case AUDIO_FORMAT_PCM_8_24_BIT:
8271 in->bit_width = 24;
8272 break;
8273 default:
8274 in->bit_width = 16;
8275 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008276 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308277 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008278 if (config->sample_rate == 0)
8279 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8280 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8281 config->sample_rate != 8000) {
8282 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8283 ret = -EINVAL;
8284 goto err_open;
8285 }
8286 if (config->format == AUDIO_FORMAT_DEFAULT)
8287 config->format = AUDIO_FORMAT_PCM_16_BIT;
8288 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8289 config->format = AUDIO_FORMAT_PCM_16_BIT;
8290 ret = -EINVAL;
8291 goto err_open;
8292 }
8293
8294 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8295 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008296 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008297 in->af_period_multiplier = 1;
8298 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8299 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8300 (config->sample_rate == 8000 ||
8301 config->sample_rate == 16000 ||
8302 config->sample_rate == 32000 ||
8303 config->sample_rate == 48000) &&
8304 channel_count == 1) {
8305 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8306 in->config = pcm_config_audio_capture;
8307 frame_size = audio_stream_in_frame_size(&in->stream);
8308 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8309 config->sample_rate,
8310 config->format,
8311 channel_count, false /*is_low_latency*/);
8312 in->config.period_size = buffer_size / frame_size;
8313 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8314 in->config.rate = config->sample_rate;
8315 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008316 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308317 int ret_val;
8318 pthread_mutex_lock(&adev->lock);
8319 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8320 in, config, &channel_mask_updated);
8321 pthread_mutex_unlock(&adev->lock);
8322
8323 if (!ret_val) {
8324 if (channel_mask_updated == true) {
8325 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8326 __func__, config->channel_mask);
8327 ret = -EINVAL;
8328 goto err_open;
8329 }
8330 ALOGD("%s: created multi-channel session succesfully",__func__);
8331 } else if (audio_extn_compr_cap_enabled() &&
8332 audio_extn_compr_cap_format_supported(config->format) &&
8333 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8334 audio_extn_compr_cap_init(in);
8335 } else if (audio_extn_cin_applicable_stream(in)) {
8336 ret = audio_extn_cin_configure_input_stream(in);
8337 if (ret)
8338 goto err_open;
8339 } else {
8340 in->config = pcm_config_audio_capture;
8341 in->config.rate = config->sample_rate;
8342 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308343 in->format = config->format;
8344 frame_size = audio_stream_in_frame_size(&in->stream);
8345 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008346 config->format,
8347 channel_count,
8348 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008349 /* prevent division-by-zero */
8350 if (frame_size == 0) {
8351 ALOGE("%s: Error frame_size==0", __func__);
8352 ret = -EINVAL;
8353 goto err_open;
8354 }
8355
Revathi Uddarajud2634032017-12-07 14:42:34 +05308356 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008357 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008358
Revathi Uddarajud2634032017-12-07 14:42:34 +05308359 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8360 /* optionally use VOIP usecase depending on config(s) */
8361 ret = adev_update_voice_comm_input_stream(in, config);
8362 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008363
Revathi Uddarajud2634032017-12-07 14:42:34 +05308364 if (ret) {
8365 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8366 goto err_open;
8367 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008368 }
kunleiz28c73e72019-03-27 17:24:04 +08008369#ifdef CONCURRENT_CAPTURE_ENABLED
8370 /* Acquire lock to avoid two concurrent use cases initialized to
8371 same pcm record use case */
8372
8373 pthread_mutex_lock(&adev->lock);
8374 if (in->usecase == USECASE_AUDIO_RECORD) {
8375 if (!(adev->pcm_record_uc_state)) {
8376 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8377 adev->pcm_record_uc_state = 1;
8378 } else {
8379 /* Assign compress record use case for second record */
8380 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8381 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8382 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8383 }
8384 }
8385 pthread_mutex_unlock(&adev->lock);
8386#endif
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008387 }
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008388
8389 in->config.channels = channel_count;
8390 in->sample_rate = in->config.rate;
8391
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308392 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8393 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008394 devices, flags, in->format,
8395 in->sample_rate, in->bit_width,
8396 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308397 register_format(in->format, in->supported_formats);
8398 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8399 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308400
Aalique Grahame22e49102018-12-18 14:23:57 -08008401 in->error_log = error_log_create(
8402 ERROR_LOG_ENTRIES,
8403 1000000000 /* aggregate consecutive identical errors within one second */);
8404
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008405 /* This stream could be for sound trigger lab,
8406 get sound trigger pcm if present */
8407 audio_extn_sound_trigger_check_and_get_session(in);
8408
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308409 lock_input_stream(in);
8410 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8411 pthread_mutex_lock(&adev->lock);
8412 in->card_status = adev->card_status;
8413 pthread_mutex_unlock(&adev->lock);
8414 pthread_mutex_unlock(&in->lock);
8415
Aalique Grahame22e49102018-12-18 14:23:57 -08008416 stream_app_type_cfg_init(&in->app_type_cfg);
8417
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008418 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008419
8420 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8421 calloc(1, sizeof(streams_input_ctxt_t));
8422 if (in_ctxt == NULL) {
8423 ALOGE("%s fail to allocate input ctxt", __func__);
8424 ret = -ENOMEM;
8425 goto err_open;
8426 }
8427 in_ctxt->input = in;
8428
8429 pthread_mutex_lock(&adev->lock);
8430 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8431 pthread_mutex_unlock(&adev->lock);
8432
Eric Laurent994a6932013-07-17 11:51:42 -07008433 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008434 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008435
8436err_open:
8437 free(in);
8438 *stream_in = NULL;
8439 return ret;
8440}
8441
8442static void adev_close_input_stream(struct audio_hw_device *dev,
8443 struct audio_stream_in *stream)
8444{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008445 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008446 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008447 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308448
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308449 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008450
kunleiz70e57612018-12-28 17:50:23 +08008451 /* must deregister from sndmonitor first to prevent races
8452 * between the callback and close_stream
8453 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308454 audio_extn_snd_mon_unregister_listener(stream);
8455
kunleiz70e57612018-12-28 17:50:23 +08008456 /* Disable echo reference if there are no active input, hfp call
8457 * and sound trigger while closing input stream
8458 */
8459 if (!adev->active_input &&
8460 !audio_extn_hfp_is_active(adev) &&
8461 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008462 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008463 else
8464 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308465
Pallavid7c7a272018-01-16 11:22:55 +05308466 if (in == NULL) {
8467 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8468 return;
8469 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08008470 error_log_destroy(in->error_log);
8471 in->error_log = NULL;
8472
Pallavid7c7a272018-01-16 11:22:55 +05308473
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008474 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308475 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008476 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308477 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008478 if (ret != 0)
8479 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8480 __func__, ret);
8481 } else
8482 in_standby(&stream->common);
8483
Revathi Uddarajud2634032017-12-07 14:42:34 +05308484 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308485 if (in->usecase == USECASE_AUDIO_RECORD) {
8486 adev->pcm_record_uc_state = 0;
8487 }
8488
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008489 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008490 audio_extn_ssr_deinit();
8491 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008492
Garmond Leunge2433c32017-09-28 21:51:22 -07008493 if (audio_extn_ffv_get_stream() == in) {
8494 audio_extn_ffv_stream_deinit();
8495 }
8496
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308497 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008498 audio_extn_compr_cap_format_supported(in->config.format))
8499 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308500
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308501 if (audio_extn_cin_attached_usecase(in->usecase))
8502 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008503
Mingming Yinfd7607b2016-01-22 12:48:44 -08008504 if (in->is_st_session) {
8505 ALOGV("%s: sound trigger pcm stop lab", __func__);
8506 audio_extn_sound_trigger_stop_lab(in);
8507 }
Derek Chenf939fb72018-11-13 13:34:41 -08008508 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8509 if (in_ctxt != NULL) {
8510 list_remove(&in_ctxt->list);
8511 free(in_ctxt);
8512 } else {
8513 ALOGW("%s, input stream already closed", __func__);
8514 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008515 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308516 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008517 return;
8518}
8519
Aalique Grahame22e49102018-12-18 14:23:57 -08008520/* verifies input and output devices and their capabilities.
8521 *
8522 * This verification is required when enabling extended bit-depth or
8523 * sampling rates, as not all qcom products support it.
8524 *
8525 * Suitable for calling only on initialization such as adev_open().
8526 * It fills the audio_device use_case_table[] array.
8527 *
8528 * Has a side-effect that it needs to configure audio routing / devices
8529 * in order to power up the devices and read the device parameters.
8530 * It does not acquire any hw device lock. Should restore the devices
8531 * back to "normal state" upon completion.
8532 */
8533static int adev_verify_devices(struct audio_device *adev)
8534{
8535 /* enumeration is a bit difficult because one really wants to pull
8536 * the use_case, device id, etc from the hidden pcm_device_table[].
8537 * In this case there are the following use cases and device ids.
8538 *
8539 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8540 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8541 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8542 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8543 * [USECASE_AUDIO_RECORD] = {0, 0},
8544 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8545 * [USECASE_VOICE_CALL] = {2, 2},
8546 *
8547 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8548 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8549 */
8550
8551 /* should be the usecases enabled in adev_open_input_stream() */
8552 static const int test_in_usecases[] = {
8553 USECASE_AUDIO_RECORD,
8554 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8555 };
8556 /* should be the usecases enabled in adev_open_output_stream()*/
8557 static const int test_out_usecases[] = {
8558 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8559 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8560 };
8561 static const usecase_type_t usecase_type_by_dir[] = {
8562 PCM_PLAYBACK,
8563 PCM_CAPTURE,
8564 };
8565 static const unsigned flags_by_dir[] = {
8566 PCM_OUT,
8567 PCM_IN,
8568 };
8569
8570 size_t i;
8571 unsigned dir;
8572 const unsigned card_id = adev->snd_card;
8573
8574 for (dir = 0; dir < 2; ++dir) {
8575 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8576 const unsigned flags_dir = flags_by_dir[dir];
8577 const size_t testsize =
8578 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8579 const int *testcases =
8580 dir ? test_in_usecases : test_out_usecases;
8581 const audio_devices_t audio_device =
8582 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8583
8584 for (i = 0; i < testsize; ++i) {
8585 const audio_usecase_t audio_usecase = testcases[i];
8586 int device_id;
8587 struct pcm_params **pparams;
8588 struct stream_out out;
8589 struct stream_in in;
8590 struct audio_usecase uc_info;
8591 int retval;
8592
8593 pparams = &adev->use_case_table[audio_usecase];
8594 pcm_params_free(*pparams); /* can accept null input */
8595 *pparams = NULL;
8596
8597 /* find the device ID for the use case (signed, for error) */
8598 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8599 if (device_id < 0)
8600 continue;
8601
8602 /* prepare structures for device probing */
8603 memset(&uc_info, 0, sizeof(uc_info));
8604 uc_info.id = audio_usecase;
8605 uc_info.type = usecase_type;
8606 if (dir) {
8607 adev->active_input = &in;
8608 memset(&in, 0, sizeof(in));
8609 in.device = audio_device;
8610 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8611 uc_info.stream.in = &in;
8612 } else {
8613 adev->active_input = NULL;
8614 }
8615 memset(&out, 0, sizeof(out));
8616 out.devices = audio_device; /* only field needed in select_devices */
8617 uc_info.stream.out = &out;
8618 uc_info.devices = audio_device;
8619 uc_info.in_snd_device = SND_DEVICE_NONE;
8620 uc_info.out_snd_device = SND_DEVICE_NONE;
8621 list_add_tail(&adev->usecase_list, &uc_info.list);
8622
8623 /* select device - similar to start_(in/out)put_stream() */
8624 retval = select_devices(adev, audio_usecase);
8625 if (retval >= 0) {
8626 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8627#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07008628 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08008629 if (*pparams) {
8630 ALOGV("%s: (%s) card %d device %d", __func__,
8631 dir ? "input" : "output", card_id, device_id);
8632 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8633 } else {
8634 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8635 }
8636#endif
8637 }
8638
8639 /* deselect device - similar to stop_(in/out)put_stream() */
8640 /* 1. Get and set stream specific mixer controls */
8641 retval = disable_audio_route(adev, &uc_info);
8642 /* 2. Disable the rx device */
8643 retval = disable_snd_device(adev,
8644 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8645 list_remove(&uc_info.list);
8646 }
8647 }
8648 adev->active_input = NULL; /* restore adev state */
8649 return 0;
8650}
8651
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308652int adev_create_audio_patch(struct audio_hw_device *dev,
8653 unsigned int num_sources,
8654 const struct audio_port_config *sources,
8655 unsigned int num_sinks,
8656 const struct audio_port_config *sinks,
8657 audio_patch_handle_t *handle)
8658{
Derek Chenf939fb72018-11-13 13:34:41 -08008659 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308660
Derek Chenf939fb72018-11-13 13:34:41 -08008661 ret = audio_extn_hw_loopback_create_audio_patch(dev,
8662 num_sources,
8663 sources,
8664 num_sinks,
8665 sinks,
8666 handle);
8667 ret |= audio_extn_auto_hal_create_audio_patch(dev,
8668 num_sources,
8669 sources,
8670 num_sinks,
8671 sinks,
8672 handle);
8673 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308674}
8675
8676int adev_release_audio_patch(struct audio_hw_device *dev,
8677 audio_patch_handle_t handle)
8678{
Derek Chenf939fb72018-11-13 13:34:41 -08008679 int ret;
8680
8681 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
8682 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
8683 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308684}
8685
8686int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8687{
8688 return audio_extn_hw_loopback_get_audio_port(dev, config);
8689}
8690
8691int adev_set_audio_port_config(struct audio_hw_device *dev,
8692 const struct audio_port_config *config)
8693{
8694 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8695}
8696
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008697static int adev_dump(const audio_hw_device_t *device __unused,
8698 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008699{
8700 return 0;
8701}
8702
8703static int adev_close(hw_device_t *device)
8704{
Aalique Grahame22e49102018-12-18 14:23:57 -08008705 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008706 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008707
8708 if (!adev)
8709 return 0;
8710
8711 pthread_mutex_lock(&adev_init_lock);
8712
8713 if ((--audio_device_ref_count) == 0) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308714 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008715 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008716 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008717 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008718 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308719 audio_extn_utils_release_streams_cfg_lists(
8720 &adev->streams_output_cfg_list,
8721 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308722 if (audio_extn_qaf_is_enabled())
8723 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008724 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08008725 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07008726 free(adev->snd_dev_ref_cnt);
8727 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008728 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8729 pcm_params_free(adev->use_case_table[i]);
8730 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008731 if (adev->adm_deinit)
8732 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308733 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008734 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308735 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308736 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008737 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308738 if (adev->device_cfg_params) {
8739 free(adev->device_cfg_params);
8740 adev->device_cfg_params = NULL;
8741 }
Derek Chend2530072014-11-24 12:39:14 -08008742 if(adev->ext_hw_plugin)
8743 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08008744 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008745 free(device);
8746 adev = NULL;
8747 }
8748 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308749 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008750 return 0;
8751}
8752
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008753/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8754 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8755 * just that it _might_ work.
8756 */
8757static int period_size_is_plausible_for_low_latency(int period_size)
8758{
8759 switch (period_size) {
8760 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07008761 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008762 case 240:
8763 case 320:
8764 case 480:
8765 return 1;
8766 default:
8767 return 0;
8768 }
8769}
8770
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308771static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
8772{
8773 bool is_snd_card_status = false;
8774 bool is_ext_device_status = false;
8775 char value[32];
8776 int card = -1;
8777 card_status_t status;
8778
8779 if (cookie != adev || !parms)
8780 return;
8781
8782 if (!parse_snd_card_status(parms, &card, &status)) {
8783 is_snd_card_status = true;
8784 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
8785 is_ext_device_status = true;
8786 } else {
8787 // not a valid event
8788 return;
8789 }
8790
8791 pthread_mutex_lock(&adev->lock);
8792 if (card == adev->snd_card || is_ext_device_status) {
8793 if (is_snd_card_status && adev->card_status != status) {
8794 adev->card_status = status;
8795 platform_snd_card_update(adev->platform, status);
8796 audio_extn_fm_set_parameters(adev, parms);
8797 } else if (is_ext_device_status) {
8798 platform_set_parameters(adev->platform, parms);
8799 }
8800 }
8801 pthread_mutex_unlock(&adev->lock);
8802 return;
8803}
8804
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05308805/* out and adev lock held */
8806static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
8807{
8808 struct audio_usecase *uc_info;
8809 float left_p;
8810 float right_p;
8811 audio_devices_t devices;
8812
8813 uc_info = get_usecase_from_list(adev, out->usecase);
8814 if (uc_info == NULL) {
8815 ALOGE("%s: Could not find the usecase (%d) in the list",
8816 __func__, out->usecase);
8817 return -EINVAL;
8818 }
8819
8820 ALOGD("%s: enter: usecase(%d: %s)", __func__,
8821 out->usecase, use_case_table[out->usecase]);
8822
8823 if (restore) {
8824 // restore A2DP device for active usecases and unmute if required
8825 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
8826 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
8827 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
8828 select_devices(adev, uc_info->id);
8829 pthread_mutex_lock(&out->compr_mute_lock);
8830 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8831 (out->a2dp_compress_mute)) {
8832 out->a2dp_compress_mute = false;
8833 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
8834 }
8835 pthread_mutex_unlock(&out->compr_mute_lock);
8836 }
8837 } else {
8838 // mute compress stream if suspended
8839 pthread_mutex_lock(&out->compr_mute_lock);
8840 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
8841 (!out->a2dp_compress_mute)) {
8842 if (!out->standby) {
8843 ALOGD("%s: selecting speaker and muting stream", __func__);
8844 devices = out->devices;
8845 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
8846 left_p = out->volume_l;
8847 right_p = out->volume_r;
8848 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8849 compress_pause(out->compr);
8850 out_set_compr_volume(&out->stream, (float)0, (float)0);
8851 out->a2dp_compress_mute = true;
8852 select_devices(adev, out->usecase);
8853 if (out->offload_state == OFFLOAD_STATE_PLAYING)
8854 compress_resume(out->compr);
8855 out->devices = devices;
8856 out->volume_l = left_p;
8857 out->volume_r = right_p;
8858 }
8859 }
8860 pthread_mutex_unlock(&out->compr_mute_lock);
8861 }
8862 ALOGV("%s: exit", __func__);
8863 return 0;
8864}
8865
8866int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
8867{
8868 int ret = 0;
8869
8870 lock_output_stream(out);
8871 pthread_mutex_lock(&adev->lock);
8872
8873 ret = check_a2dp_restore_l(adev, out, restore);
8874
8875 pthread_mutex_unlock(&adev->lock);
8876 pthread_mutex_unlock(&out->lock);
8877 return ret;
8878}
8879
Haynes Mathew George01156f92018-04-13 15:29:54 -07008880void adev_on_battery_status_changed(bool charging)
8881{
8882 pthread_mutex_lock(&adev->lock);
8883 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
8884 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08008885 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07008886 pthread_mutex_unlock(&adev->lock);
8887}
8888
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008889static int adev_open(const hw_module_t *module, const char *name,
8890 hw_device_t **device)
8891{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308892 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08008893 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308894 char mixer_ctl_name[128] = {0};
8895 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308896
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008897 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008898 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
8899
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008900 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07008901 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008902 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07008903 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07008904 ALOGD("%s: returning existing instance of adev", __func__);
8905 ALOGD("%s: exit", __func__);
8906 pthread_mutex_unlock(&adev_init_lock);
8907 return 0;
8908 }
8909
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008910 adev = calloc(1, sizeof(struct audio_device));
8911
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008912 if (!adev) {
8913 pthread_mutex_unlock(&adev_init_lock);
8914 return -ENOMEM;
8915 }
8916
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008917 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
8918
Weiyin Jiange6ce6312019-01-28 18:28:22 +08008919 // register audio ext hidl at the earliest
8920 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05308921#ifdef DYNAMIC_LOG_ENABLED
8922 register_for_dynamic_logging("hal");
8923#endif
8924
Derek Chenf939fb72018-11-13 13:34:41 -08008925 /* default audio HAL major version */
8926 uint32_t maj_version = 2;
8927 if(property_get("vendor.audio.hal.maj.version", value, NULL))
8928 maj_version = atoi(value);
8929
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008930 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08008931 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008932 adev->device.common.module = (struct hw_module_t *)module;
8933 adev->device.common.close = adev_close;
8934
8935 adev->device.init_check = adev_init_check;
8936 adev->device.set_voice_volume = adev_set_voice_volume;
8937 adev->device.set_master_volume = adev_set_master_volume;
8938 adev->device.get_master_volume = adev_get_master_volume;
8939 adev->device.set_master_mute = adev_set_master_mute;
8940 adev->device.get_master_mute = adev_get_master_mute;
8941 adev->device.set_mode = adev_set_mode;
8942 adev->device.set_mic_mute = adev_set_mic_mute;
8943 adev->device.get_mic_mute = adev_get_mic_mute;
8944 adev->device.set_parameters = adev_set_parameters;
8945 adev->device.get_parameters = adev_get_parameters;
8946 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
8947 adev->device.open_output_stream = adev_open_output_stream;
8948 adev->device.close_output_stream = adev_close_output_stream;
8949 adev->device.open_input_stream = adev_open_input_stream;
8950 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308951 adev->device.create_audio_patch = adev_create_audio_patch;
8952 adev->device.release_audio_patch = adev_release_audio_patch;
8953 adev->device.get_audio_port = adev_get_audio_port;
8954 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008955 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308956 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008957
8958 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008959 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08008960 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08008961 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008962 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008963 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08008964 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07008965 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05308966 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07008967 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07008968 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
Aniket Kumar Lata808e8d62019-01-28 22:54:28 -08008969 /* Init audio feature manager */
8970 audio_feature_manager_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008971 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08008972 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08008973 list_init(&adev->active_inputs_list);
8974 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08008975 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07008976 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05308977 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05308978 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05308979 adev->perf_lock_opts[0] = 0x101;
8980 adev->perf_lock_opts[1] = 0x20E;
8981 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08008982 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07008983 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05308984 adev->use_old_pspd_mix_ctrl = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05308985
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008986 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07008987 adev->platform = platform_init(adev);
8988 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07008989 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008990 free(adev->snd_dev_ref_cnt);
8991 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07008992 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07008993 ALOGE("%s: Failed to init platform data, aborting.", __func__);
8994 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08008995 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07008996 return -EINVAL;
8997 }
Eric Laurentc4aef752013-09-12 17:45:53 -07008998
Aalique Grahame22e49102018-12-18 14:23:57 -08008999 adev->extspk = audio_extn_extspk_init(adev);
9000
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309001 if (audio_extn_qaf_is_enabled()) {
9002 ret = audio_extn_qaf_init(adev);
9003 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009004 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309005 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009006 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309007 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9008 *device = NULL;
9009 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309010 return ret;
9011 }
9012
9013 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9014 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9015 }
9016
Derek Chenae7b0342019-02-08 15:17:04 -08009017 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009018 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9019
Eric Laurentc4aef752013-09-12 17:45:53 -07009020 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9021 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9022 if (adev->visualizer_lib == NULL) {
9023 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9024 } else {
9025 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9026 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009027 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009028 "visualizer_hal_start_output");
9029 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009030 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009031 "visualizer_hal_stop_output");
9032 }
9033 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309034 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009035 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009036 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009037 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309038 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009039 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009040
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009041 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9042 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9043 if (adev->offload_effects_lib == NULL) {
9044 ALOGE("%s: DLOPEN failed for %s", __func__,
9045 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9046 } else {
9047 ALOGV("%s: DLOPEN successful for %s", __func__,
9048 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9049 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309050 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009051 "offload_effects_bundle_hal_start_output");
9052 adev->offload_effects_stop_output =
9053 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9054 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009055 adev->offload_effects_set_hpx_state =
9056 (int (*)(bool))dlsym(adev->offload_effects_lib,
9057 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309058 adev->offload_effects_get_parameters =
9059 (void (*)(struct str_parms *, struct str_parms *))
9060 dlsym(adev->offload_effects_lib,
9061 "offload_effects_bundle_get_parameters");
9062 adev->offload_effects_set_parameters =
9063 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9064 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009065 }
9066 }
9067
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009068 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9069 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9070 if (adev->adm_lib == NULL) {
9071 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9072 } else {
9073 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9074 adev->adm_init = (adm_init_t)
9075 dlsym(adev->adm_lib, "adm_init");
9076 adev->adm_deinit = (adm_deinit_t)
9077 dlsym(adev->adm_lib, "adm_deinit");
9078 adev->adm_register_input_stream = (adm_register_input_stream_t)
9079 dlsym(adev->adm_lib, "adm_register_input_stream");
9080 adev->adm_register_output_stream = (adm_register_output_stream_t)
9081 dlsym(adev->adm_lib, "adm_register_output_stream");
9082 adev->adm_deregister_stream = (adm_deregister_stream_t)
9083 dlsym(adev->adm_lib, "adm_deregister_stream");
9084 adev->adm_request_focus = (adm_request_focus_t)
9085 dlsym(adev->adm_lib, "adm_request_focus");
9086 adev->adm_abandon_focus = (adm_abandon_focus_t)
9087 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009088 adev->adm_set_config = (adm_set_config_t)
9089 dlsym(adev->adm_lib, "adm_set_config");
9090 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9091 dlsym(adev->adm_lib, "adm_request_focus_v2");
9092 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9093 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9094 adev->adm_on_routing_change = (adm_on_routing_change_t)
9095 dlsym(adev->adm_lib, "adm_on_routing_change");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009096 }
9097 }
9098
Aalique Grahame22e49102018-12-18 14:23:57 -08009099 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009100 adev->bt_wb_speech_enabled = false;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009101 //initialize this to false for now,
9102 //this will be set to true through set param
9103 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009104
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009105 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009106 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009107
9108 if (k_enable_extended_precision)
9109 adev_verify_devices(adev);
9110
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009111 adev->dsp_bit_width_enforce_mode =
9112 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009113
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309114 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9115 &adev->streams_output_cfg_list,
9116 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009117
Kiran Kandi910e1862013-10-29 13:29:42 -07009118 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009119
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009120 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009121 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9122 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009123 trial = atoi(value);
9124 if (period_size_is_plausible_for_low_latency(trial)) {
9125 pcm_config_low_latency.period_size = trial;
9126 pcm_config_low_latency.start_threshold = trial / 4;
9127 pcm_config_low_latency.avail_min = trial / 4;
9128 configured_low_latency_capture_period_size = trial;
9129 }
9130 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009131 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9132 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009133 trial = atoi(value);
9134 if (period_size_is_plausible_for_low_latency(trial)) {
9135 configured_low_latency_capture_period_size = trial;
9136 }
9137 }
9138
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009139 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9140
Aalique Grahame22e49102018-12-18 14:23:57 -08009141 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9142 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009143 af_period_multiplier = atoi(value);
9144 if (af_period_multiplier < 0)
9145 af_period_multiplier = 2;
9146 else if (af_period_multiplier > 4)
9147 af_period_multiplier = 4;
9148
9149 ALOGV("new period_multiplier = %d", af_period_multiplier);
9150 }
9151
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009152 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009153
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009154 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009155 pthread_mutex_unlock(&adev_init_lock);
9156
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009157 if (adev->adm_init)
9158 adev->adm_data = adev->adm_init();
9159
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309160 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309161 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009162 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309163
9164 audio_extn_snd_mon_init();
9165 pthread_mutex_lock(&adev->lock);
9166 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9167 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009168 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9169 /*
9170 * if the battery state callback happens before charging can be queried,
9171 * it will be guarded with the adev->lock held in the cb function and so
9172 * the callback value will reflect the latest state
9173 */
9174 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309175 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009176 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009177 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009178 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309179 /* Allocate memory for Device config params */
9180 adev->device_cfg_params = (struct audio_device_config_param*)
9181 calloc(platform_get_max_codec_backend(),
9182 sizeof(struct audio_device_config_param));
9183 if (adev->device_cfg_params == NULL)
9184 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309185
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309186 /*
9187 * Check if new PSPD matrix mixer control is supported. If not
9188 * supported, then set flag so that old mixer ctrl is sent while
9189 * sending pspd coefficients on older kernel version. Query mixer
9190 * control for default pcm id and channel value one.
9191 */
9192 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9193 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9194
9195 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9196 if (!ctl) {
9197 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9198 __func__, mixer_ctl_name);
9199 adev->use_old_pspd_mix_ctrl = true;
9200 }
9201
Eric Laurent994a6932013-07-17 11:51:42 -07009202 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009203 return 0;
9204}
9205
9206static struct hw_module_methods_t hal_module_methods = {
9207 .open = adev_open,
9208};
9209
9210struct audio_module HAL_MODULE_INFO_SYM = {
9211 .common = {
9212 .tag = HARDWARE_MODULE_TAG,
9213 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9214 .hal_api_version = HARDWARE_HAL_API_VERSION,
9215 .id = AUDIO_HARDWARE_MODULE_ID,
9216 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009217 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009218 .methods = &hal_module_methods,
9219 },
9220};