blob: b2c23fe97572133fb21743e7400b47a6a2cb712b [file] [log] [blame]
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001/*
Aalique Grahame22e49102018-12-18 14:23:57 -08002 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -07003 * Not a Contribution.
4 *
Shiv Maliyappanahalli8911f282014-01-10 15:56:19 -08005 * Copyright (C) 2013 The Android Open Source Project
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Jitendra Naruka1b6513f2014-11-22 19:34:13 -080018 *
19 * This file was modified by DTS, Inc. The portions of the
20 * code modified by DTS, Inc are copyrighted and
21 * licensed separately, as follows:
22 *
23 * (C) 2014 DTS, Inc.
24 *
25 * Licensed under the Apache License, Version 2.0 (the "License");
26 * you may not use this file except in compliance with the License.
27 * You may obtain a copy of the License at
28 *
29 * http://www.apache.org/licenses/LICENSE-2.0
30 *
31 * Unless required by applicable law or agreed to in writing, software
32 * distributed under the License is distributed on an "AS IS" BASIS,
33 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
34 * See the License for the specific language governing permissions and
35 * limitations under the License.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080036 */
37
38#define LOG_TAG "audio_hw_primary"
Haynes Mathew George5beddd42016-06-27 18:33:40 -070039#define ATRACE_TAG (ATRACE_TAG_AUDIO|ATRACE_TAG_HAL)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080040/*#define LOG_NDEBUG 0*/
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070041/*#define VERY_VERY_VERBOSE_LOGGING*/
42#ifdef VERY_VERY_VERBOSE_LOGGING
43#define ALOGVV ALOGV
44#else
45#define ALOGVV(a...) do { } while(0)
46#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080047
48#include <errno.h>
49#include <pthread.h>
50#include <stdint.h>
51#include <sys/time.h>
52#include <stdlib.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080053#include <math.h>
Eric Laurentc4aef752013-09-12 17:45:53 -070054#include <dlfcn.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070055#include <sys/resource.h>
56#include <sys/prctl.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080057
Aalique Grahame22e49102018-12-18 14:23:57 -080058#include <log/log.h>
Haynes Mathew George5beddd42016-06-27 18:33:40 -070059#include <cutils/trace.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080060#include <cutils/str_parms.h>
61#include <cutils/properties.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070062#include <cutils/atomic.h>
63#include <cutils/sched_policy.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070064#include <hardware/audio_effect.h>
Haynes Mathew George484e8d22017-07-31 18:55:17 -070065#include <hardware/audio_alsaops.h>
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070066#include <system/thread_defs.h>
Haynes Mathew George16081042017-05-31 17:16:49 -070067#include <tinyalsa/asoundlib.h>
Eric Laurentb23d5282013-05-14 15:27:20 -070068#include <audio_effects/effect_aec.h>
69#include <audio_effects/effect_ns.h>
Ashish Jainf1eaa582016-05-23 20:54:24 +053070#include <audio_utils/format.h>
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080071#include "audio_hw.h"
Wei Wangf7ca6c92017-11-21 14:51:20 -080072#include "audio_perf.h"
Eric Laurentb23d5282013-05-14 15:27:20 -070073#include "platform_api.h"
74#include <platform.h>
Apoorv Raghuvanshi9eaf94e2013-10-04 16:13:44 -070075#include "audio_extn.h"
Narsinga Rao Chella05573b72013-11-15 15:21:40 -080076#include "voice_extn.h"
Ashish Jaind5694242017-09-05 20:09:06 +053077#include "ip_hdlr_intf.h"
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -080078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070079#include "sound/compress_params.h"
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -080080#include "sound/asound.h"
ApurupaPattapu2e084df2013-12-18 15:47:59 -080081
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +053082#ifdef DYNAMIC_LOG_ENABLED
83#include <log_xml_parser.h>
84#define LOG_MASK HAL_MOD_FILE_AUDIO_HW
85#include <log_utils.h>
86#endif
87
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070088#define COMPRESS_OFFLOAD_NUM_FRAGMENTS 4
Ashish Jain5106d362016-05-11 19:23:33 +053089/*DIRECT PCM has same buffer sizes as DEEP Buffer*/
90#define DIRECT_PCM_NUM_FRAGMENTS 2
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070091#define COMPRESS_PLAYBACK_VOLUME_MAX 0x2000
Vikram Panduranga93f080e2017-06-07 18:16:14 -070092#define VOIP_PLAYBACK_VOLUME_MAX 0x2000
Arun Mirpuri5d170872019-03-26 13:21:31 -070093#define MMAP_PLAYBACK_VOLUME_MAX 0x2000
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +053094#define PCM_PLAYBACK_VOLUME_MAX 0x2000
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +053095#define DSD_VOLUME_MIN_DB (-110)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -070096
Aalique Grahame22e49102018-12-18 14:23:57 -080097#define RECORD_GAIN_MIN 0.0f
98#define RECORD_GAIN_MAX 1.0f
99#define RECORD_VOLUME_CTL_MAX 0x2000
100
101/* treat as unsigned Q1.13 */
102#define APP_TYPE_GAIN_DEFAULT 0x2000
103
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700104#define PROXY_OPEN_RETRY_COUNT 100
105#define PROXY_OPEN_WAIT_TIME 20
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800106
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800107#define GET_USECASE_AUDIO_PLAYBACK_PRIMARY(db) \
108 (db)? USECASE_AUDIO_PLAYBACK_DEEP_BUFFER : \
109 USECASE_AUDIO_PLAYBACK_LOW_LATENCY
110#define GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(db) \
111 (db)? pcm_config_deep_buffer : pcm_config_low_latency
Haynes Mathew Georgebf143712013-12-03 13:02:53 -0800112
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700113#define ULL_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700114#define DEFAULT_VOIP_BUF_DURATION_MS 20
115#define DEFAULT_VOIP_BIT_DEPTH_BYTE sizeof(int16_t)
116#define DEFAULT_VOIP_SAMP_RATE 48000
117
118#define VOIP_IO_BUF_SIZE(SR, DURATION_MS, BIT_DEPTH) (SR)/1000 * DURATION_MS * BIT_DEPTH
119
120struct pcm_config default_pcm_config_voip_copp = {
121 .channels = 1,
122 .rate = DEFAULT_VOIP_SAMP_RATE, /* changed when the stream is opened */
123 .period_size = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
124 .period_count = 2,
125 .format = PCM_FORMAT_S16_LE,
kunleiz95b597a2017-10-23 17:07:33 +0800126 .avail_min = VOIP_IO_BUF_SIZE(DEFAULT_VOIP_SAMP_RATE, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2,
127 .stop_threshold = INT_MAX,
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700128};
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700129
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700130#define MIN_CHANNEL_COUNT 1
131#define DEFAULT_CHANNEL_COUNT 2
132#define MAX_HIFI_CHANNEL_COUNT 8
133
Aalique Grahame22e49102018-12-18 14:23:57 -0800134#ifndef MAX_TARGET_SPECIFIC_CHANNEL_CNT
135#define MAX_CHANNEL_COUNT 1
136#else
137#define MAX_CHANNEL_COUNT atoi(XSTR(MAX_TARGET_SPECIFIC_CHANNEL_CNT))
138#define XSTR(x) STR(x)
139#define STR(x) #x
140#endif
141
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -0700142static unsigned int configured_low_latency_capture_period_size =
143 LOW_LATENCY_CAPTURE_PERIOD_SIZE;
144
Haynes Mathew George16081042017-05-31 17:16:49 -0700145#define MMAP_PERIOD_SIZE (DEFAULT_OUTPUT_SAMPLING_RATE/1000)
146#define MMAP_PERIOD_COUNT_MIN 32
147#define MMAP_PERIOD_COUNT_MAX 512
148#define MMAP_PERIOD_COUNT_DEFAULT (MMAP_PERIOD_COUNT_MAX)
149
Aalique Grahame22e49102018-12-18 14:23:57 -0800150/* This constant enables extended precision handling.
151 * TODO The flag is off until more testing is done.
152 */
153static const bool k_enable_extended_precision = false;
Arun Mirpurie008ed22019-03-21 11:21:04 -0700154extern int AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Aalique Grahame22e49102018-12-18 14:23:57 -0800155
Eric Laurentb23d5282013-05-14 15:27:20 -0700156struct pcm_config pcm_config_deep_buffer = {
157 .channels = 2,
158 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
159 .period_size = DEEP_BUFFER_OUTPUT_PERIOD_SIZE,
160 .period_count = DEEP_BUFFER_OUTPUT_PERIOD_COUNT,
161 .format = PCM_FORMAT_S16_LE,
162 .start_threshold = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
163 .stop_threshold = INT_MAX,
164 .avail_min = DEEP_BUFFER_OUTPUT_PERIOD_SIZE / 4,
165};
166
167struct pcm_config pcm_config_low_latency = {
168 .channels = 2,
169 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
170 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
171 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
172 .format = PCM_FORMAT_S16_LE,
173 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
174 .stop_threshold = INT_MAX,
175 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
176};
177
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800178struct pcm_config pcm_config_haptics_audio = {
179 .channels = 1,
180 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
181 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
182 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
183 .format = PCM_FORMAT_S16_LE,
184 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
185 .stop_threshold = INT_MAX,
186 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
187};
188
189struct pcm_config pcm_config_haptics = {
190 .channels = 1,
191 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
192 .period_size = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
193 .period_count = LOW_LATENCY_OUTPUT_PERIOD_COUNT,
194 .format = PCM_FORMAT_S16_LE,
195 .start_threshold = LOW_LATENCY_OUTPUT_PERIOD_SIZE,
196 .stop_threshold = INT_MAX,
197 .avail_min = LOW_LATENCY_OUTPUT_PERIOD_SIZE / 4,
198};
199
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700200static int af_period_multiplier = 4;
201struct pcm_config pcm_config_rt = {
202 .channels = 2,
203 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
204 .period_size = ULL_PERIOD_SIZE, //1 ms
205 .period_count = 512, //=> buffer size is 512ms
206 .format = PCM_FORMAT_S16_LE,
207 .start_threshold = ULL_PERIOD_SIZE*8, //8ms
208 .stop_threshold = INT_MAX,
209 .silence_threshold = 0,
210 .silence_size = 0,
211 .avail_min = ULL_PERIOD_SIZE, //1 ms
212};
213
Eric Laurentb23d5282013-05-14 15:27:20 -0700214struct pcm_config pcm_config_hdmi_multi = {
215 .channels = HDMI_MULTI_DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
216 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
217 .period_size = HDMI_MULTI_PERIOD_SIZE,
218 .period_count = HDMI_MULTI_PERIOD_COUNT,
219 .format = PCM_FORMAT_S16_LE,
220 .start_threshold = 0,
221 .stop_threshold = INT_MAX,
222 .avail_min = 0,
223};
224
Haynes Mathew George16081042017-05-31 17:16:49 -0700225struct pcm_config pcm_config_mmap_playback = {
226 .channels = 2,
227 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
228 .period_size = MMAP_PERIOD_SIZE,
229 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
230 .format = PCM_FORMAT_S16_LE,
231 .start_threshold = MMAP_PERIOD_SIZE*8,
232 .stop_threshold = INT32_MAX,
233 .silence_threshold = 0,
234 .silence_size = 0,
235 .avail_min = MMAP_PERIOD_SIZE, //1 ms
236};
237
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700238struct pcm_config pcm_config_hifi = {
239 .channels = DEFAULT_CHANNEL_COUNT, /* changed when the stream is opened */
240 .rate = DEFAULT_OUTPUT_SAMPLING_RATE, /* changed when the stream is opened */
241 .period_size = HIFI_BUFFER_OUTPUT_PERIOD_SIZE, /* change #define */
242 .period_count = HIFI_BUFFER_OUTPUT_PERIOD_COUNT,
243 .format = PCM_FORMAT_S24_3LE,
244 .start_threshold = 0,
245 .stop_threshold = INT_MAX,
246 .avail_min = 0,
247};
248
Eric Laurentb23d5282013-05-14 15:27:20 -0700249struct pcm_config pcm_config_audio_capture = {
250 .channels = 2,
Eric Laurentb23d5282013-05-14 15:27:20 -0700251 .period_count = AUDIO_CAPTURE_PERIOD_COUNT,
252 .format = PCM_FORMAT_S16_LE,
253};
254
Haynes Mathew George16081042017-05-31 17:16:49 -0700255struct pcm_config pcm_config_mmap_capture = {
256 .channels = 2,
257 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
258 .period_size = MMAP_PERIOD_SIZE,
259 .period_count = MMAP_PERIOD_COUNT_DEFAULT,
260 .format = PCM_FORMAT_S16_LE,
261 .start_threshold = 0,
262 .stop_threshold = INT_MAX,
263 .silence_threshold = 0,
264 .silence_size = 0,
265 .avail_min = MMAP_PERIOD_SIZE, //1 ms
266};
267
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700268#define AFE_PROXY_CHANNEL_COUNT 2
269#define AFE_PROXY_SAMPLING_RATE 48000
270
271#define AFE_PROXY_PLAYBACK_PERIOD_SIZE 768
272#define AFE_PROXY_PLAYBACK_PERIOD_COUNT 4
273
274struct pcm_config pcm_config_afe_proxy_playback = {
275 .channels = AFE_PROXY_CHANNEL_COUNT,
276 .rate = AFE_PROXY_SAMPLING_RATE,
277 .period_size = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
278 .period_count = AFE_PROXY_PLAYBACK_PERIOD_COUNT,
279 .format = PCM_FORMAT_S16_LE,
280 .start_threshold = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
281 .stop_threshold = INT_MAX,
282 .avail_min = AFE_PROXY_PLAYBACK_PERIOD_SIZE,
283};
284
285#define AFE_PROXY_RECORD_PERIOD_SIZE 768
286#define AFE_PROXY_RECORD_PERIOD_COUNT 4
287
Aalique Grahame22e49102018-12-18 14:23:57 -0800288struct pcm_config pcm_config_audio_capture_rt = {
289 .channels = 2,
290 .rate = DEFAULT_OUTPUT_SAMPLING_RATE,
291 .period_size = ULL_PERIOD_SIZE,
292 .period_count = 512,
293 .format = PCM_FORMAT_S16_LE,
294 .start_threshold = 0,
295 .stop_threshold = AFE_PROXY_RECORD_PERIOD_SIZE * AFE_PROXY_RECORD_PERIOD_COUNT,
296 .silence_threshold = 0,
297 .silence_size = 0,
298 .avail_min = ULL_PERIOD_SIZE, //1 ms
299};
300
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700301struct pcm_config pcm_config_afe_proxy_record = {
302 .channels = AFE_PROXY_CHANNEL_COUNT,
303 .rate = AFE_PROXY_SAMPLING_RATE,
304 .period_size = AFE_PROXY_RECORD_PERIOD_SIZE,
305 .period_count = AFE_PROXY_RECORD_PERIOD_COUNT,
306 .format = PCM_FORMAT_S16_LE,
307 .start_threshold = AFE_PROXY_RECORD_PERIOD_SIZE,
308 .stop_threshold = INT_MAX,
309 .avail_min = AFE_PROXY_RECORD_PERIOD_SIZE,
310};
311
Ashish Jainf1eaa582016-05-23 20:54:24 +0530312#define AUDIO_MAX_PCM_FORMATS 7
313
314const uint32_t format_to_bitwidth_table[AUDIO_MAX_PCM_FORMATS] = {
315 [AUDIO_FORMAT_DEFAULT] = 0,
316 [AUDIO_FORMAT_PCM_16_BIT] = sizeof(uint16_t),
317 [AUDIO_FORMAT_PCM_8_BIT] = sizeof(uint8_t),
318 [AUDIO_FORMAT_PCM_32_BIT] = sizeof(uint32_t),
319 [AUDIO_FORMAT_PCM_8_24_BIT] = sizeof(uint32_t),
320 [AUDIO_FORMAT_PCM_FLOAT] = sizeof(float),
321 [AUDIO_FORMAT_PCM_24_BIT_PACKED] = sizeof(uint8_t) * 3,
322};
323
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -0800324const char * const use_case_table[AUDIO_USECASE_MAX] = {
Eric Laurentb23d5282013-05-14 15:27:20 -0700325 [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = "deep-buffer-playback",
326 [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = "low-latency-playback",
Vignesh Kulothungana6927272019-02-20 15:17:07 -0800327 [USECASE_AUDIO_PLAYBACK_WITH_HAPTICS] = "audio-with-haptics-playback",
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -0700328 [USECASE_AUDIO_PLAYBACK_ULL] = "audio-ull-playback",
329 [USECASE_AUDIO_PLAYBACK_MULTI_CH] = "multi-channel-playback",
Shruthi Krishnaace10852013-10-25 14:32:12 -0700330 [USECASE_AUDIO_PLAYBACK_OFFLOAD] = "compress-offload-playback",
vivek mehta446c3962015-09-14 10:57:35 -0700331 //Enabled for Direct_PCM
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700332 [USECASE_AUDIO_PLAYBACK_OFFLOAD2] = "compress-offload-playback2",
333 [USECASE_AUDIO_PLAYBACK_OFFLOAD3] = "compress-offload-playback3",
334 [USECASE_AUDIO_PLAYBACK_OFFLOAD4] = "compress-offload-playback4",
335 [USECASE_AUDIO_PLAYBACK_OFFLOAD5] = "compress-offload-playback5",
336 [USECASE_AUDIO_PLAYBACK_OFFLOAD6] = "compress-offload-playback6",
337 [USECASE_AUDIO_PLAYBACK_OFFLOAD7] = "compress-offload-playback7",
338 [USECASE_AUDIO_PLAYBACK_OFFLOAD8] = "compress-offload-playback8",
339 [USECASE_AUDIO_PLAYBACK_OFFLOAD9] = "compress-offload-playback9",
Haynes Mathew George16081042017-05-31 17:16:49 -0700340 [USECASE_AUDIO_PLAYBACK_FM] = "play-fm",
341 [USECASE_AUDIO_PLAYBACK_MMAP] = "mmap-playback",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700342 [USECASE_AUDIO_PLAYBACK_HIFI] = "hifi-playback",
Aalique Grahame22e49102018-12-18 14:23:57 -0800343 [USECASE_AUDIO_PLAYBACK_TTS] = "audio-tts-playback",
vivek mehta0ea887a2015-08-26 14:01:20 -0700344
Eric Laurentb23d5282013-05-14 15:27:20 -0700345 [USECASE_AUDIO_RECORD] = "audio-record",
Mingming Yine62d7842013-10-25 16:26:03 -0700346 [USECASE_AUDIO_RECORD_COMPRESS] = "audio-record-compress",
Dhananjay Kumaree4d2002016-10-25 18:02:58 +0530347 [USECASE_AUDIO_RECORD_COMPRESS2] = "audio-record-compress2",
348 [USECASE_AUDIO_RECORD_COMPRESS3] = "audio-record-compress3",
349 [USECASE_AUDIO_RECORD_COMPRESS4] = "audio-record-compress4",
Dhananjay Kumar376e38b2017-09-28 22:26:23 +0530350 [USECASE_AUDIO_RECORD_COMPRESS5] = "audio-record-compress5",
351 [USECASE_AUDIO_RECORD_COMPRESS6] = "audio-record-compress6",
Eric Laurentb23d5282013-05-14 15:27:20 -0700352 [USECASE_AUDIO_RECORD_LOW_LATENCY] = "low-latency-record",
Preetam Singh Ranawatde84f1a2013-11-01 14:58:16 -0700353 [USECASE_AUDIO_RECORD_FM_VIRTUAL] = "fm-virtual-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700354 [USECASE_AUDIO_RECORD_MMAP] = "mmap-record",
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700355 [USECASE_AUDIO_RECORD_HIFI] = "hifi-record",
Haynes Mathew George16081042017-05-31 17:16:49 -0700356
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -0800357 [USECASE_AUDIO_HFP_SCO] = "hfp-sco",
Vimal Puthanveed47e64852013-12-20 13:23:39 -0800358 [USECASE_AUDIO_HFP_SCO_WB] = "hfp-sco-wb",
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700359 [USECASE_VOICE_CALL] = "voice-call",
Mingming Yin3ee55c62014-08-04 14:23:35 -0700360
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -0700361 [USECASE_VOICE2_CALL] = "voice2-call",
362 [USECASE_VOLTE_CALL] = "volte-call",
363 [USECASE_QCHAT_CALL] = "qchat-call",
Vicky Sehrawat7e4fc152014-02-12 17:58:59 -0800364 [USECASE_VOWLAN_CALL] = "vowlan-call",
Vidyakumar Athota0e109352015-02-12 17:38:22 -0800365 [USECASE_VOICEMMODE1_CALL] = "voicemmode1-call",
366 [USECASE_VOICEMMODE2_CALL] = "voicemmode2-call",
Narsinga Rao Chella05573b72013-11-15 15:21:40 -0800367 [USECASE_COMPRESS_VOIP_CALL] = "compress-voip-call",
Shiv Maliyappanahallida107642013-10-17 11:16:13 -0700368 [USECASE_INCALL_REC_UPLINK] = "incall-rec-uplink",
369 [USECASE_INCALL_REC_DOWNLINK] = "incall-rec-downlink",
370 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK] = "incall-rec-uplink-and-downlink",
Helen Zenge56b4852013-12-03 16:54:40 -0800371 [USECASE_INCALL_REC_UPLINK_COMPRESS] = "incall-rec-uplink-compress",
372 [USECASE_INCALL_REC_DOWNLINK_COMPRESS] = "incall-rec-downlink-compress",
373 [USECASE_INCALL_REC_UPLINK_AND_DOWNLINK_COMPRESS] = "incall-rec-uplink-and-downlink-compress",
374
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -0700375 [USECASE_INCALL_MUSIC_UPLINK] = "incall_music_uplink",
376 [USECASE_INCALL_MUSIC_UPLINK2] = "incall_music_uplink2",
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -0700377 [USECASE_AUDIO_SPKR_CALIB_RX] = "spkr-rx-calib",
378 [USECASE_AUDIO_SPKR_CALIB_TX] = "spkr-vi-record",
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -0700379
380 [USECASE_AUDIO_PLAYBACK_AFE_PROXY] = "afe-proxy-playback",
381 [USECASE_AUDIO_RECORD_AFE_PROXY] = "afe-proxy-record",
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +0530382 [USECASE_AUDIO_PLAYBACK_SILENCE] = "silence-playback",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700383
Siddartha Shaik31b530e2017-05-19 15:26:33 +0530384 /* Transcode loopback cases */
Surendar Karka93cd25a2018-08-28 14:21:37 +0530385 [USECASE_AUDIO_TRANSCODE_LOOPBACK_RX] = "audio-transcode-loopback-rx",
386 [USECASE_AUDIO_TRANSCODE_LOOPBACK_TX] = "audio-transcode-loopback-tx",
Vikram Panduranga93f080e2017-06-07 18:16:14 -0700387
388 [USECASE_AUDIO_PLAYBACK_VOIP] = "audio-playback-voip",
389 [USECASE_AUDIO_RECORD_VOIP] = "audio-record-voip",
Varun Balaraje49253e2017-07-06 19:48:56 +0530390 /* For Interactive Audio Streams */
391 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1] = "audio-interactive-stream1",
392 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2] = "audio-interactive-stream2",
393 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3] = "audio-interactive-stream3",
394 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4] = "audio-interactive-stream4",
395 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5] = "audio-interactive-stream5",
396 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6] = "audio-interactive-stream6",
397 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7] = "audio-interactive-stream7",
398 [USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8] = "audio-interactive-stream8",
Garmond Leunge2433c32017-09-28 21:51:22 -0700399
Aniket Kumar Lata7fd86e12018-02-20 19:26:10 -0800400 [USECASE_AUDIO_EC_REF_LOOPBACK] = "ec-ref-audio-capture",
401
Derek Chenf6318be2017-06-12 17:16:24 -0400402 [USECASE_AUDIO_A2DP_ABR_FEEDBACK] = "a2dp-abr-feedback",
403
404 [USECASE_AUDIO_PLAYBACK_MEDIA] = "media-playback",
405 [USECASE_AUDIO_PLAYBACK_SYS_NOTIFICATION] = "sys-notification-playback",
406 [USECASE_AUDIO_PLAYBACK_NAV_GUIDANCE] = "nav-guidance-playback",
407 [USECASE_AUDIO_PLAYBACK_PHONE] = "phone-playback",
Eric Laurentb23d5282013-05-14 15:27:20 -0700408};
409
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700410static const audio_usecase_t offload_usecases[] = {
411 USECASE_AUDIO_PLAYBACK_OFFLOAD,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700412 USECASE_AUDIO_PLAYBACK_OFFLOAD2,
413 USECASE_AUDIO_PLAYBACK_OFFLOAD3,
414 USECASE_AUDIO_PLAYBACK_OFFLOAD4,
415 USECASE_AUDIO_PLAYBACK_OFFLOAD5,
416 USECASE_AUDIO_PLAYBACK_OFFLOAD6,
417 USECASE_AUDIO_PLAYBACK_OFFLOAD7,
418 USECASE_AUDIO_PLAYBACK_OFFLOAD8,
419 USECASE_AUDIO_PLAYBACK_OFFLOAD9,
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -0700420};
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800421
Varun Balaraje49253e2017-07-06 19:48:56 +0530422static const audio_usecase_t interactive_usecases[] = {
423 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM1,
424 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM2,
425 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM3,
426 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM4,
427 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM5,
428 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM6,
429 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM7,
430 USECASE_AUDIO_PLAYBACK_INTERACTIVE_STREAM8,
431};
432
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800433#define STRING_TO_ENUM(string) { #string, string }
434
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800435struct string_to_enum {
436 const char *name;
437 uint32_t value;
438};
439
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700440static const struct string_to_enum channels_name_to_enum_table[] = {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800441 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_STEREO),
Mingming Yin3a941d42016-02-17 18:08:05 -0800442 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_2POINT1),
443 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_QUAD),
444 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_SURROUND),
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -0700445 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_PENTA),
Mingming Yin3a941d42016-02-17 18:08:05 -0800446 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_5POINT1),
447 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_6POINT1),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800448 STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700449 STRING_TO_ENUM(AUDIO_CHANNEL_IN_MONO),
450 STRING_TO_ENUM(AUDIO_CHANNEL_IN_STEREO),
451 STRING_TO_ENUM(AUDIO_CHANNEL_IN_FRONT_BACK),
452 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_1),
453 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_2),
454 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_3),
455 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_4),
456 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_5),
457 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_6),
458 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_7),
459 STRING_TO_ENUM(AUDIO_CHANNEL_INDEX_MASK_8),
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -0800460};
461
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700462static const struct string_to_enum formats_name_to_enum_table[] = {
463 STRING_TO_ENUM(AUDIO_FORMAT_PCM_16_BIT),
464 STRING_TO_ENUM(AUDIO_FORMAT_PCM_24_BIT_PACKED),
465 STRING_TO_ENUM(AUDIO_FORMAT_PCM_32_BIT),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700466 STRING_TO_ENUM(AUDIO_FORMAT_AC3),
467 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3),
468 STRING_TO_ENUM(AUDIO_FORMAT_E_AC3_JOC),
Ben Romberger1aaaf862017-04-06 17:49:46 -0700469 STRING_TO_ENUM(AUDIO_FORMAT_DOLBY_TRUEHD),
Mingming Yin3a941d42016-02-17 18:08:05 -0800470 STRING_TO_ENUM(AUDIO_FORMAT_DTS),
471 STRING_TO_ENUM(AUDIO_FORMAT_DTS_HD),
Naresh Tanniru928f0862017-04-07 16:44:23 -0700472 STRING_TO_ENUM(AUDIO_FORMAT_IEC61937)
Mingming Yin3a941d42016-02-17 18:08:05 -0800473};
474
475//list of all supported sample rates by HDMI specification.
476static const int out_hdmi_sample_rates[] = {
477 32000, 44100, 48000, 88200, 96000, 176400, 192000,
478};
479
Haynes Mathew George484e8d22017-07-31 18:55:17 -0700480static const struct string_to_enum out_sample_rates_name_to_enum_table[] = {
Mingming Yin3a941d42016-02-17 18:08:05 -0800481 STRING_TO_ENUM(32000),
482 STRING_TO_ENUM(44100),
483 STRING_TO_ENUM(48000),
484 STRING_TO_ENUM(88200),
485 STRING_TO_ENUM(96000),
486 STRING_TO_ENUM(176400),
487 STRING_TO_ENUM(192000),
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -0700488};
489
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -0700490static struct audio_device *adev = NULL;
Ben Romberger02ab1192018-05-24 12:10:08 -0700491static pthread_mutex_t adev_init_lock = PTHREAD_MUTEX_INITIALIZER;
Kiran Kandi910e1862013-10-29 13:29:42 -0700492static unsigned int audio_device_ref_count;
vivek mehtab72d08d2016-04-29 03:16:47 -0700493//cache last MBDRC cal step level
494static int last_known_cal_step = -1 ;
Kiran Kandi910e1862013-10-29 13:29:42 -0700495
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530496static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore);
497static int out_set_compr_volume(struct audio_stream_out *stream, float left, float right);
Arun Mirpuri5d170872019-03-26 13:21:31 -0700498static int out_set_mmap_volume(struct audio_stream_out *stream, float left, float right);
Zhou Song2b8f28f2017-09-11 10:51:38 +0800499static int out_set_voip_volume(struct audio_stream_out *stream, float left, float right);
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +0530500static int out_set_pcm_volume(struct audio_stream_out *stream, float left, float right);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +0530501
Vatsal Buchac09ae062018-11-14 13:25:08 +0530502#ifdef AUDIO_FEATURE_ENABLED_GCOV
503extern void __gcov_flush();
504static void enable_gcov()
505{
506 __gcov_flush();
507}
508#else
509static void enable_gcov()
510{
511}
512#endif
513
justinweng20fb6d82019-02-21 18:49:00 -0700514static int in_set_microphone_direction(const struct audio_stream_in *stream,
515 audio_microphone_direction_t dir);
516static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom);
517
518
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700519static bool may_use_noirq_mode(struct audio_device *adev, audio_usecase_t uc_id,
520 int flags __unused)
521{
522 int dir = 0;
523 switch (uc_id) {
524 case USECASE_AUDIO_RECORD_LOW_LATENCY:
525 dir = 1;
526 case USECASE_AUDIO_PLAYBACK_ULL:
527 break;
528 default:
529 return false;
530 }
531
532 int dev_id = platform_get_pcm_device_id(uc_id, dir == 0 ?
533 PCM_PLAYBACK : PCM_CAPTURE);
534 if (adev->adm_is_noirq_avail)
535 return adev->adm_is_noirq_avail(adev->adm_data,
536 adev->snd_card, dev_id, dir);
537 return false;
538}
539
540static void register_out_stream(struct stream_out *out)
541{
542 struct audio_device *adev = out->dev;
543 if (is_offload_usecase(out->usecase) ||
544 !adev->adm_register_output_stream)
545 return;
546
547 // register stream first for backward compatibility
548 adev->adm_register_output_stream(adev->adm_data,
549 out->handle,
550 out->flags);
551
552 if (!adev->adm_set_config)
553 return;
554
555 if (out->realtime)
556 adev->adm_set_config(adev->adm_data,
557 out->handle,
558 out->pcm, &out->config);
559}
560
561static void register_in_stream(struct stream_in *in)
562{
563 struct audio_device *adev = in->dev;
564 if (!adev->adm_register_input_stream)
565 return;
566
567 adev->adm_register_input_stream(adev->adm_data,
568 in->capture_handle,
569 in->flags);
570
571 if (!adev->adm_set_config)
572 return;
573
574 if (in->realtime)
575 adev->adm_set_config(adev->adm_data,
576 in->capture_handle,
577 in->pcm,
578 &in->config);
579}
580
581static void request_out_focus(struct stream_out *out, long ns)
582{
583 struct audio_device *adev = out->dev;
584
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700585 if (adev->adm_request_focus_v2)
586 adev->adm_request_focus_v2(adev->adm_data, out->handle, ns);
587 else if (adev->adm_request_focus)
588 adev->adm_request_focus(adev->adm_data, out->handle);
589}
590
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700591static int request_in_focus(struct stream_in *in, long ns)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700592{
593 struct audio_device *adev = in->dev;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700594 int ret = 0;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700595
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700596 if (adev->adm_request_focus_v2_1)
597 ret = adev->adm_request_focus_v2_1(adev->adm_data, in->capture_handle, ns);
598 else if (adev->adm_request_focus_v2)
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700599 adev->adm_request_focus_v2(adev->adm_data, in->capture_handle, ns);
600 else if (adev->adm_request_focus)
601 adev->adm_request_focus(adev->adm_data, in->capture_handle);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -0700602
603 return ret;
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700604}
605
606static void release_out_focus(struct stream_out *out)
607{
608 struct audio_device *adev = out->dev;
609
610 if (adev->adm_abandon_focus)
611 adev->adm_abandon_focus(adev->adm_data, out->handle);
612}
613
614static void release_in_focus(struct stream_in *in)
615{
616 struct audio_device *adev = in->dev;
617 if (adev->adm_abandon_focus)
618 adev->adm_abandon_focus(adev->adm_data, in->capture_handle);
619}
620
Dhananjay Kumare6293dd2017-05-25 17:25:30 +0530621static int parse_snd_card_status(struct str_parms *parms, int *card,
622 card_status_t *status)
623{
624 char value[32]={0};
625 char state[32]={0};
626
627 int ret = str_parms_get_str(parms, "SND_CARD_STATUS", value, sizeof(value));
628 if (ret < 0)
629 return -1;
630
631 // sscanf should be okay as value is of max length 32.
632 // same as sizeof state.
633 if (sscanf(value, "%d,%s", card, state) < 2)
634 return -1;
635
636 *status = !strcmp(state, "ONLINE") ? CARD_STATUS_ONLINE :
637 CARD_STATUS_OFFLINE;
638 return 0;
639}
640
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -0700641static inline void adjust_frames_for_device_delay(struct stream_out *out,
642 uint32_t *dsp_frames) {
643 // Adjustment accounts for A2dp encoder latency with offload usecases
644 // Note: Encoder latency is returned in ms.
645 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
646 unsigned long offset =
647 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
648 *dsp_frames = (*dsp_frames > offset) ? (*dsp_frames - offset) : 0;
649 }
650}
651
vivek mehtaa76401a2015-04-24 14:12:15 -0700652__attribute__ ((visibility ("default")))
653bool audio_hw_send_gain_dep_calibration(int level) {
654 bool ret_val = false;
vivek mehtab72d08d2016-04-29 03:16:47 -0700655 ALOGV("%s: called ...", __func__);
vivek mehtaa76401a2015-04-24 14:12:15 -0700656
657 pthread_mutex_lock(&adev_init_lock);
658
659 if (adev != NULL && adev->platform != NULL) {
660 pthread_mutex_lock(&adev->lock);
661 ret_val = platform_send_gain_dep_cal(adev->platform, level);
vivek mehtab72d08d2016-04-29 03:16:47 -0700662
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +0530663 // cache level info for any of the use case which
664 // was not started.
665 last_known_cal_step = level;;
vivek mehtab72d08d2016-04-29 03:16:47 -0700666
vivek mehtaa76401a2015-04-24 14:12:15 -0700667 pthread_mutex_unlock(&adev->lock);
668 } else {
669 ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
670 }
671
672 pthread_mutex_unlock(&adev_init_lock);
673
674 return ret_val;
675}
676
Ashish Jain5106d362016-05-11 19:23:33 +0530677static int check_and_set_gapless_mode(struct audio_device *adev, bool enable_gapless)
678{
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800679 bool gapless_enabled = false;
680 const char *mixer_ctl_name = "Compress Gapless Playback";
681 struct mixer_ctl *ctl;
682
683 ALOGV("%s:", __func__);
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -0700684 gapless_enabled = property_get_bool("vendor.audio.offload.gapless.enabled", false);
Ashish Jain5106d362016-05-11 19:23:33 +0530685
686 /*Disable gapless if its AV playback*/
687 gapless_enabled = gapless_enabled && enable_gapless;
Krishnankutty Kolathappilly6d8788b2014-01-09 12:45:31 -0800688
689 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
690 if (!ctl) {
691 ALOGE("%s: Could not get ctl for mixer cmd - %s",
692 __func__, mixer_ctl_name);
693 return -EINVAL;
694 }
695
696 if (mixer_ctl_set_value(ctl, 0, gapless_enabled) < 0) {
697 ALOGE("%s: Could not set gapless mode %d",
698 __func__, gapless_enabled);
699 return -EINVAL;
700 }
701 return 0;
702}
Haynes Mathew George5191a852013-09-11 14:19:36 -0700703
Aniket Kumar Lataf56b6402016-10-27 12:03:18 -0700704__attribute__ ((visibility ("default")))
705int audio_hw_get_gain_level_mapping(struct amp_db_and_gain_table *mapping_tbl,
706 int table_size) {
707 int ret_val = 0;
708 ALOGV("%s: enter ... ", __func__);
709
710 pthread_mutex_lock(&adev_init_lock);
711 if (adev == NULL) {
712 ALOGW("%s: adev is NULL .... ", __func__);
713 goto done;
714 }
715
716 pthread_mutex_lock(&adev->lock);
717 ret_val = platform_get_gain_level_mapping(mapping_tbl, table_size);
718 pthread_mutex_unlock(&adev->lock);
719done:
720 pthread_mutex_unlock(&adev_init_lock);
721 ALOGV("%s: exit ... ", __func__);
722 return ret_val;
723}
724
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800725bool audio_hw_send_qdsp_parameter(int stream_type, float vol, bool active)
Aalique Grahame22e49102018-12-18 14:23:57 -0800726{
727 bool ret = false;
728 ALOGV("%s: enter ...", __func__);
729
730 pthread_mutex_lock(&adev_init_lock);
731
732 if (adev != NULL && adev->platform != NULL) {
733 pthread_mutex_lock(&adev->lock);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800734 ret = audio_extn_qdsp_set_state(adev, stream_type, vol, active);
Aalique Grahame22e49102018-12-18 14:23:57 -0800735 pthread_mutex_unlock(&adev->lock);
736 }
737
738 pthread_mutex_unlock(&adev_init_lock);
739
740 ALOGV("%s: exit with ret %d", __func__, ret);
741 return ret;
742}
Aalique Grahame22e49102018-12-18 14:23:57 -0800743
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700744static bool is_supported_format(audio_format_t format)
745{
Eric Laurent86e17132013-09-12 17:49:30 -0700746 if (format == AUDIO_FORMAT_MP3 ||
Satish Babu Patakokila0c313922016-12-08 12:07:08 +0530747 format == AUDIO_FORMAT_MP2 ||
Ashish Jainf9b78162014-08-25 20:36:25 +0530748 format == AUDIO_FORMAT_AAC_LC ||
749 format == AUDIO_FORMAT_AAC_HE_V1 ||
750 format == AUDIO_FORMAT_AAC_HE_V2 ||
Manish Dewangana6fc5442015-08-24 20:30:31 +0530751 format == AUDIO_FORMAT_AAC_ADTS_LC ||
752 format == AUDIO_FORMAT_AAC_ADTS_HE_V1 ||
753 format == AUDIO_FORMAT_AAC_ADTS_HE_V2 ||
Arun Kumar Dasari3b174182016-12-27 13:01:14 +0530754 format == AUDIO_FORMAT_AAC_LATM_LC ||
755 format == AUDIO_FORMAT_AAC_LATM_HE_V1 ||
756 format == AUDIO_FORMAT_AAC_LATM_HE_V2 ||
Ashish Jain5106d362016-05-11 19:23:33 +0530757 format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
758 format == AUDIO_FORMAT_PCM_8_24_BIT ||
Ashish Jainf1eaa582016-05-23 20:54:24 +0530759 format == AUDIO_FORMAT_PCM_FLOAT ||
760 format == AUDIO_FORMAT_PCM_32_BIT ||
vivek mehta0ea887a2015-08-26 14:01:20 -0700761 format == AUDIO_FORMAT_PCM_16_BIT ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530762 format == AUDIO_FORMAT_AC3 ||
763 format == AUDIO_FORMAT_E_AC3 ||
Ben Romberger1aaaf862017-04-06 17:49:46 -0700764 format == AUDIO_FORMAT_DOLBY_TRUEHD ||
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +0530765 format == AUDIO_FORMAT_DTS ||
766 format == AUDIO_FORMAT_DTS_HD ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800767 format == AUDIO_FORMAT_FLAC ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530768 format == AUDIO_FORMAT_ALAC ||
769 format == AUDIO_FORMAT_APE ||
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +0530770 format == AUDIO_FORMAT_DSD ||
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +0530771 format == AUDIO_FORMAT_VORBIS ||
Weiyin Jiang18ac4e92015-03-15 15:03:40 +0800772 format == AUDIO_FORMAT_WMA ||
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +0530773 format == AUDIO_FORMAT_WMA_PRO ||
Naresh Tanniru928f0862017-04-07 16:44:23 -0700774 format == AUDIO_FORMAT_APTX ||
775 format == AUDIO_FORMAT_IEC61937)
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -0800776 return true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -0700777
778 return false;
779}
780
Haynes Mathew George5beddd42016-06-27 18:33:40 -0700781static inline bool is_mmap_usecase(audio_usecase_t uc_id)
782{
783 return (uc_id == USECASE_AUDIO_RECORD_AFE_PROXY) ||
784 (uc_id == USECASE_AUDIO_PLAYBACK_AFE_PROXY);
785}
786
Avinash Vaish71a8b972014-07-24 15:36:33 +0530787static int enable_audio_route_for_voice_usecases(struct audio_device *adev,
788 struct audio_usecase *uc_info)
789{
790 struct listnode *node;
791 struct audio_usecase *usecase;
792
793 if (uc_info == NULL)
794 return -EINVAL;
795
796 /* Re-route all voice usecases on the shared backend other than the
797 specified usecase to new snd devices */
798 list_for_each(node, &adev->usecase_list) {
799 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellae7f33c12015-01-28 15:23:34 -0800800 if ((usecase->type == VOICE_CALL) && (usecase != uc_info))
Avinash Vaish71a8b972014-07-24 15:36:33 +0530801 enable_audio_route(adev, usecase);
802 }
803 return 0;
804}
805
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530806static void enable_asrc_mode(struct audio_device *adev)
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530807{
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530808 ALOGV("%s", __func__);
809 audio_route_apply_and_update_path(adev->audio_route,
810 "asrc-mode");
811 adev->asrc_mode_enabled = true;
812}
813
814static void disable_asrc_mode(struct audio_device *adev)
815{
816 ALOGV("%s", __func__);
817 audio_route_reset_and_update_path(adev->audio_route,
818 "asrc-mode");
819 adev->asrc_mode_enabled = false;
820}
821
822/*
823 * - Enable ASRC mode for incoming mix path use case(Headphone backend)if Headphone
824 * 44.1 or Native DSD backends are enabled for any of current use case.
825 * e.g. 48-> + (Naitve DSD or Headphone 44.1)
826 * - Disable current mix path use case(Headphone backend) and re-enable it with
827 * ASRC mode for incoming Headphone 44.1 or Native DSD use case.
828 * e.g. Naitve DSD or Headphone 44.1 -> + 48
829 */
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530830static void check_and_set_asrc_mode(struct audio_device *adev,
831 struct audio_usecase *uc_info,
832 snd_device_t snd_device)
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530833{
834 ALOGV("%s snd device %d", __func__, snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530835 int i, num_new_devices = 0;
836 snd_device_t split_new_snd_devices[SND_DEVICE_OUT_END];
837 /*
838 *Split snd device for new combo use case
839 *e.g. Headphopne 44.1-> + Ringtone (Headphone + Speaker)
840 */
841 if (platform_split_snd_device(adev->platform,
842 snd_device,
843 &num_new_devices,
844 split_new_snd_devices) == 0) {
845 for (i = 0; i < num_new_devices; i++)
846 check_and_set_asrc_mode(adev, uc_info, split_new_snd_devices[i]);
847 } else {
848 int new_backend_idx = platform_get_backend_index(snd_device);
849 if (((new_backend_idx == HEADPHONE_BACKEND) ||
850 (new_backend_idx == HEADPHONE_44_1_BACKEND) ||
851 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
852 !adev->asrc_mode_enabled) {
853 struct listnode *node = NULL;
854 struct audio_usecase *uc = NULL;
855 struct stream_out *curr_out = NULL;
856 int usecase_backend_idx = DEFAULT_CODEC_BACKEND;
857 int i, num_devices, ret = 0;
858 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +0530859
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530860 list_for_each(node, &adev->usecase_list) {
861 uc = node_to_item(node, struct audio_usecase, list);
862 curr_out = (struct stream_out*) uc->stream.out;
863 if (curr_out && PCM_PLAYBACK == uc->type && uc != uc_info) {
864 /*
865 *Split snd device for existing combo use case
866 *e.g. Ringtone (Headphone + Speaker) + Headphopne 44.1
867 */
868 ret = platform_split_snd_device(adev->platform,
869 uc->out_snd_device,
870 &num_devices,
871 split_snd_devices);
872 if (ret < 0 || num_devices == 0) {
873 ALOGV("%s: Unable to split uc->out_snd_device: %d",__func__, uc->out_snd_device);
874 split_snd_devices[0] = uc->out_snd_device;
875 num_devices = 1;
Garmond Leung50058f62017-02-08 09:49:30 -0800876 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530877 for (i = 0; i < num_devices; i++) {
878 usecase_backend_idx = platform_get_backend_index(split_snd_devices[i]);
879 ALOGD("%s:snd_dev %d usecase_backend_idx %d",__func__, split_snd_devices[i],usecase_backend_idx);
880 if((new_backend_idx == HEADPHONE_BACKEND) &&
881 ((usecase_backend_idx == HEADPHONE_44_1_BACKEND) ||
882 (usecase_backend_idx == DSD_NATIVE_BACKEND))) {
883 ALOGD("%s:DSD or native stream detected enabling asrcmode in hardware",
884 __func__);
885 enable_asrc_mode(adev);
886 break;
887 } else if(((new_backend_idx == HEADPHONE_44_1_BACKEND) ||
888 (new_backend_idx == DSD_NATIVE_BACKEND)) &&
889 (usecase_backend_idx == HEADPHONE_BACKEND)) {
890 ALOGD("%s:48K stream detected, disabling and enabling it with asrcmode in hardware",
891 __func__);
892 disable_audio_route(adev, uc);
893 disable_snd_device(adev, uc->out_snd_device);
894 // Apply true-high-quality-mode if DSD or > 44.1KHz or >=24-bit
895 if (new_backend_idx == DSD_NATIVE_BACKEND)
896 audio_route_apply_and_update_path(adev->audio_route,
897 "hph-true-highquality-mode");
898 else if ((new_backend_idx == HEADPHONE_44_1_BACKEND) &&
899 (curr_out->bit_width >= 24))
900 audio_route_apply_and_update_path(adev->audio_route,
901 "hph-highquality-mode");
902 enable_asrc_mode(adev);
903 enable_snd_device(adev, uc->out_snd_device);
904 enable_audio_route(adev, uc);
905 break;
906 }
907 }
908 // reset split devices count
909 num_devices = 0;
Garmond Leung50058f62017-02-08 09:49:30 -0800910 }
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +0530911 if (adev->asrc_mode_enabled)
912 break;
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +0530913 }
914 }
915 }
916}
917
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700918static int send_effect_enable_disable_mixer_ctl(struct audio_device *adev,
919 struct audio_effect_config effect_config,
920 unsigned int param_value)
921{
922 char mixer_ctl_name[] = "Audio Effect";
923 struct mixer_ctl *ctl;
924 long set_values[6];
925 struct stream_in *in = adev->active_input;
926
927 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
928 if (!ctl) {
929 ALOGE("%s: Could not get mixer ctl - %s",
930 __func__, mixer_ctl_name);
931 return -EINVAL;
932 }
933
934 set_values[0] = 1; //0:Rx 1:Tx
935 set_values[1] = in->app_type_cfg.app_type;
936 set_values[2] = (long)effect_config.module_id;
937 set_values[3] = (long)effect_config.instance_id;
938 set_values[4] = (long)effect_config.param_id;
939 set_values[5] = param_value;
940
941 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
942
943 return 0;
944
945}
946
947static int update_effect_param_ecns(struct audio_device *adev, unsigned int module_id,
948 int effect_type, unsigned int *param_value)
949{
950 int ret = 0;
951 struct audio_effect_config other_effect_config;
952 struct audio_usecase *usecase = NULL;
953 struct stream_in *in = adev->active_input;
954
955 usecase = get_usecase_from_list(adev, in->usecase);
956 if (!usecase)
957 return -EINVAL;
958
959 ret = platform_get_effect_config_data(usecase->in_snd_device, &other_effect_config,
960 effect_type == EFFECT_AEC ? EFFECT_NS : EFFECT_AEC);
961 if (ret < 0) {
962 ALOGE("%s Failed to get effect params %d", __func__, ret);
963 return ret;
964 }
965
966 if (module_id == other_effect_config.module_id) {
967 //Same module id for AEC/NS. Values need to be combined
968 if (((effect_type == EFFECT_AEC) && (in->enable_ns)) ||
969 ((effect_type == EFFECT_NS) && (in->enable_aec))) {
970 *param_value |= other_effect_config.param_value;
971 }
972 }
973
974 return ret;
975}
976
977static int enable_disable_effect(struct audio_device *adev, int effect_type, bool enable)
Gangadhar Sb0210342019-02-22 17:39:41 +0530978{
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700979 struct audio_effect_config effect_config;
980 struct audio_usecase *usecase = NULL;
981 int ret = 0;
982 unsigned int param_value = 0;
983 struct stream_in *in = adev->active_input;
984
Arun Mirpurib1bec9c2019-01-29 16:42:45 -0800985 if(!voice_extn_is_dynamic_ecns_enabled())
986 return ENOSYS;
987
Vikram Pandurangadf59cae2017-08-03 18:04:55 -0700988 if (!in) {
989 ALOGE("%s: Invalid input stream", __func__);
990 return -EINVAL;
991 }
992
993 ALOGD("%s: effect_type:%d enable:%d", __func__, effect_type, enable);
994
995 usecase = get_usecase_from_list(adev, in->usecase);
Weiyin Jiang20d3fa62018-08-01 18:06:27 +0800996 if (usecase == NULL) {
997 ALOGE("%s: Could not find the usecase (%d) in the list",
998 __func__, in->usecase);
999 return -EINVAL;
1000 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001001
1002 ret = platform_get_effect_config_data(usecase->in_snd_device, &effect_config, effect_type);
1003 if (ret < 0) {
1004 ALOGE("%s Failed to get module id %d", __func__, ret);
1005 return ret;
1006 }
1007 ALOGV("%s: %d %d usecase->id:%d usecase->in_snd_device:%d", __func__, effect_config.module_id,
1008 in->app_type_cfg.app_type, usecase->id, usecase->in_snd_device);
1009
1010 if(enable)
1011 param_value = effect_config.param_value;
1012
1013 /*Special handling for AEC & NS effects Param values need to be
1014 updated if module ids are same*/
1015
1016 if ((effect_type == EFFECT_AEC) || (effect_type == EFFECT_NS)) {
1017 ret = update_effect_param_ecns(adev, effect_config.module_id, effect_type, &param_value);
1018 if (ret < 0)
1019 return ret;
1020 }
1021
1022 ret = send_effect_enable_disable_mixer_ctl(adev, effect_config, param_value);
1023
1024 return ret;
1025}
1026
1027static void check_and_enable_effect(struct audio_device *adev)
1028{
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08001029 if(!voice_extn_is_dynamic_ecns_enabled())
1030 return;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001031
1032 if (adev->active_input->enable_aec) {
1033 enable_disable_effect(adev, EFFECT_AEC, true);
1034 }
1035
1036 if (adev->active_input->enable_ns &&
1037 adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
1038 enable_disable_effect(adev, EFFECT_NS, true);
1039 }
1040}
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07001041
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07001042int pcm_ioctl(struct pcm *pcm, int request, ...)
1043{
1044 va_list ap;
1045 void * arg;
1046 int pcm_fd = *(int*)pcm;
1047
1048 va_start(ap, request);
1049 arg = va_arg(ap, void *);
1050 va_end(ap);
1051
1052 return ioctl(pcm_fd, request, arg);
1053}
1054
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001055int enable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001056 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001057{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001058 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001059 char mixer_path[MIXER_PATH_MAX_LENGTH];
Manish Dewangan58229382017-02-02 15:48:41 +05301060 struct stream_out *out = NULL;
Soumya Managoli6993b762018-06-28 16:04:57 +05301061 int ret = 0;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001062
1063 if (usecase == NULL)
1064 return -EINVAL;
1065
1066 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
1067
Surendar Karka93cd25a2018-08-28 14:21:37 +05301068 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001069 snd_device = usecase->in_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001070 else
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001071 snd_device = usecase->out_snd_device;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001072
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08001073#ifdef DS1_DOLBY_DAP_ENABLED
1074 audio_extn_dolby_set_dmid(adev);
1075 audio_extn_dolby_set_endpoint(adev);
1076#endif
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07001077 audio_extn_dolby_ds2_set_endpoint(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001078 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301079 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_BUSY);
Ben Romberger1fafdde2015-09-09 19:43:15 -07001080 audio_extn_utils_send_app_type_cfg(adev, usecase);
Jasmine Cha4dcc1092019-03-04 18:12:47 +08001081 if (audio_extn_is_maxx_audio_enabled())
1082 audio_extn_ma_set_device(usecase);
Dhananjay Kumar14170dd2015-08-28 13:24:16 +05301083 audio_extn_utils_send_audio_calibration(adev, usecase);
Manish Dewangan58229382017-02-02 15:48:41 +05301084 if ((usecase->type == PCM_PLAYBACK) && is_offload_usecase(usecase->id)) {
1085 out = usecase->stream.out;
1086 if (out && out->compr)
1087 audio_extn_utils_compress_set_clk_rec_mode(usecase);
1088 }
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301089 audio_extn_set_custom_mtmx_params(adev, usecase, true);
Manish Dewangan58229382017-02-02 15:48:41 +05301090
Andy Hung756ecc12018-10-19 17:47:12 -07001091 // we shouldn't truncate mixer_path
1092 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1093 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1094 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001095 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001096 ALOGD("%s: apply mixer and update path: %s", __func__, mixer_path);
Soumya Managoli6993b762018-06-28 16:04:57 +05301097 ret = audio_route_apply_and_update_path(adev->audio_route, mixer_path);
1098 if (!ret && usecase->id == USECASE_AUDIO_PLAYBACK_FM) {
1099 struct str_parms *parms = str_parms_create_str("fm_restore_volume=1");
1100 if (parms) {
1101 audio_extn_fm_set_parameters(adev, parms);
1102 str_parms_destroy(parms);
1103 }
1104 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001105 ALOGV("%s: exit", __func__);
1106 return 0;
1107}
1108
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001109int disable_audio_route(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001110 struct audio_usecase *usecase)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001111{
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001112 snd_device_t snd_device;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001113 char mixer_path[MIXER_PATH_MAX_LENGTH];
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001114
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05301115 if (usecase == NULL || usecase->id == USECASE_INVALID)
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08001116 return -EINVAL;
1117
1118 ALOGV("%s: enter: usecase(%d)", __func__, usecase->id);
Surendar Karka93cd25a2018-08-28 14:21:37 +05301119 if (usecase->type == PCM_CAPTURE || usecase->type == TRANSCODE_LOOPBACK_TX)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001120 snd_device = usecase->in_snd_device;
1121 else
1122 snd_device = usecase->out_snd_device;
Andy Hung756ecc12018-10-19 17:47:12 -07001123 // we shouldn't truncate mixer_path
1124 ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
1125 >= sizeof(mixer_path), "%s: truncation on mixer path", __func__);
1126 // this also appends to mixer_path
Banajit Goswami20cdd212015-09-11 01:11:30 -07001127 platform_add_backend_name(mixer_path, snd_device, usecase);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001128 ALOGD("%s: reset and update mixer path: %s", __func__, mixer_path);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001129 audio_route_reset_and_update_path(adev->audio_route, mixer_path);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001130 audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301131 audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
Dhananjay Kumar429eb452018-12-10 22:26:53 +05301132 audio_extn_set_custom_mtmx_params(adev, usecase, false);
Weiyin Jiang298ffd92019-06-03 14:29:30 +08001133 if ((usecase->type == PCM_PLAYBACK) &&
1134 (usecase->stream.out != NULL))
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05301135 usecase->stream.out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001136 ALOGV("%s: exit", __func__);
1137 return 0;
1138}
1139
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001140int enable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001141 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001142{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301143 int i, num_devices = 0;
1144 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001145 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1146
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001147 if (snd_device < SND_DEVICE_MIN ||
1148 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001149 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001150 return -EINVAL;
1151 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001152
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001153 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001154 ALOGE("%s: Invalid sound device returned", __func__);
1155 return -EINVAL;
1156 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001157
1158 adev->snd_dev_ref_cnt[snd_device]++;
1159
1160 if ((adev->snd_dev_ref_cnt[snd_device] > 1) &&
1161 (platform_split_snd_device(adev->platform,
1162 snd_device,
1163 &num_devices,
1164 new_snd_devices) != 0)) {
Eric Laurent994a6932013-07-17 11:51:42 -07001165 ALOGV("%s: snd_device(%d: %s) is already active",
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001166 __func__, snd_device, device_name);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001167 return 0;
1168 }
1169
Gopikrishnaiah Anandane85d0462014-06-30 21:41:20 -07001170 if (audio_extn_spkr_prot_is_enabled())
1171 audio_extn_spkr_prot_calib_cancel(adev);
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001172
Aalique Grahame22e49102018-12-18 14:23:57 -08001173 audio_extn_dsm_feedback_enable(adev, snd_device, true);
1174
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001175 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1176 audio_extn_spkr_prot_is_enabled()) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001177 if (platform_get_spkr_prot_acdb_id(snd_device) < 0) {
1178 goto err;
1179 }
1180 audio_extn_dev_arbi_acquire(snd_device);
1181 if (audio_extn_spkr_prot_start_processing(snd_device)) {
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001182 ALOGE("%s: spkr_start_processing failed", __func__);
Ravit Dennisaaee49c2015-02-04 21:26:22 +02001183 audio_extn_dev_arbi_release(snd_device);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001184 goto err;
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001185 }
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001186 } else if (platform_split_snd_device(adev->platform,
1187 snd_device,
1188 &num_devices,
1189 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301190 for (i = 0; i < num_devices; i++) {
1191 enable_snd_device(adev, new_snd_devices[i]);
1192 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001193 platform_set_speaker_gain_in_combo(adev, snd_device, true);
Vidyakumar Athota1c6419a2014-01-10 14:47:34 -08001194 } else {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001195 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301196
Preetam Singh Ranawatf1d417c2017-01-10 17:00:32 +05301197
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001198 if ((SND_DEVICE_OUT_BT_A2DP == snd_device) &&
1199 (audio_extn_a2dp_start_playback() < 0)) {
1200 ALOGE(" fail to configure A2dp Source control path ");
1201 goto err;
1202 }
Florian Pfister1a84f312018-07-19 14:38:18 +02001203
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001204 if ((SND_DEVICE_IN_BT_A2DP == snd_device) &&
1205 (audio_extn_a2dp_start_capture() < 0)) {
1206 ALOGE(" fail to configure A2dp Sink control path ");
1207 goto err;
1208 }
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301209
Zhou Song12c29502019-03-16 10:37:18 +08001210 if (((SND_DEVICE_OUT_BT_SCO_SWB == snd_device) ||
1211 (SND_DEVICE_IN_BT_SCO_MIC_SWB_NREC == snd_device) ||
1212 (SND_DEVICE_IN_BT_SCO_MIC_SWB == snd_device)) &&
1213 (audio_extn_sco_start_configuration() < 0)) {
1214 ALOGE(" fail to configure sco control path ");
1215 goto err;
1216 }
1217
Bharath Ramachandramurthy0de16782014-03-28 21:34:33 -07001218 /* due to the possibility of calibration overwrite between listen
1219 and audio, notify listen hal before audio calibration is sent */
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001220 audio_extn_sound_trigger_update_device_status(snd_device,
1221 ST_EVENT_SND_DEVICE_BUSY);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301222 audio_extn_listen_update_device_status(snd_device,
1223 LISTEN_EVENT_SND_DEVICE_BUSY);
Subhash Chandra Bose Naripeddy54274672014-03-10 14:51:02 -07001224 if (platform_get_snd_device_acdb_id(snd_device) < 0) {
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001225 audio_extn_sound_trigger_update_device_status(snd_device,
1226 ST_EVENT_SND_DEVICE_FREE);
Dhananjay Kumar45b71742014-05-29 21:47:27 +05301227 audio_extn_listen_update_device_status(snd_device,
1228 LISTEN_EVENT_SND_DEVICE_FREE);
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001229 goto err;
Gopikrishnaiah Anandanf538cef2013-10-28 14:06:03 -07001230 }
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001231 audio_extn_dev_arbi_acquire(snd_device);
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001232 audio_route_apply_and_update_path(adev->audio_route, device_name);
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301233
1234 if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
1235 !adev->native_playback_enabled &&
1236 audio_is_true_native_stream_active(adev)) {
1237 ALOGD("%s: %d: napb: enabling native mode in hardware",
1238 __func__, __LINE__);
1239 audio_route_apply_and_update_path(adev->audio_route,
1240 "true-native-mode");
1241 adev->native_playback_enabled = true;
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301242 }
Dhanalakshmi Siddani10621622018-04-30 15:07:27 +05301243 if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
1244 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001245 (audio_extn_ffv_get_stream() == adev->active_input)) {
1246 ALOGD("%s: init ec ref loopback", __func__);
1247 audio_extn_ffv_init_ec_ref_loopback(adev, snd_device);
1248 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001249 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001250 return 0;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001251err:
1252 adev->snd_dev_ref_cnt[snd_device]--;
1253 return -EINVAL;;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001254}
1255
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07001256int disable_snd_device(struct audio_device *adev,
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001257 snd_device_t snd_device)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001258{
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301259 int i, num_devices = 0;
1260 snd_device_t new_snd_devices[SND_DEVICE_OUT_END];
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001261 char device_name[DEVICE_NAME_MAX_SIZE] = {0};
1262
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001263 if (snd_device < SND_DEVICE_MIN ||
1264 snd_device >= SND_DEVICE_MAX) {
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08001265 ALOGE("%s: Invalid sound device %d", __func__, snd_device);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08001266 return -EINVAL;
1267 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001268
1269 if (platform_get_snd_device_name_extn(adev->platform, snd_device, device_name) < 0) {
1270 ALOGE("%s: Invalid sound device returned", __func__);
1271 return -EINVAL;
1272 }
1273
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001274 if (adev->snd_dev_ref_cnt[snd_device] <= 0) {
1275 ALOGE("%s: device ref cnt is already 0", __func__);
1276 return -EINVAL;
1277 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001278
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001279 adev->snd_dev_ref_cnt[snd_device]--;
Apoorv Raghuvanshi5792d4b2013-10-07 18:40:05 -07001280
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001281
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001282 if (adev->snd_dev_ref_cnt[snd_device] == 0) {
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07001283 ALOGD("%s: snd_device(%d: %s)", __func__, snd_device, device_name);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301284
Aalique Grahame22e49102018-12-18 14:23:57 -08001285 audio_extn_dsm_feedback_enable(adev, snd_device, false);
1286
Xiaojun Sang040cc9f2015-08-03 19:38:28 +08001287 if (platform_can_enable_spkr_prot_on_device(snd_device) &&
1288 audio_extn_spkr_prot_is_enabled()) {
Anish Kumar46c7b872014-09-09 01:49:44 -07001289 audio_extn_spkr_prot_stop_processing(snd_device);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07001290
1291 // when speaker device is disabled, reset swap.
1292 // will be renabled on usecase start
1293 platform_set_swap_channels(adev, false);
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001294 } else if (platform_split_snd_device(adev->platform,
1295 snd_device,
1296 &num_devices,
1297 new_snd_devices) == 0) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301298 for (i = 0; i < num_devices; i++) {
1299 disable_snd_device(adev, new_snd_devices[i]);
1300 }
Aalique Grahame22e49102018-12-18 14:23:57 -08001301 platform_set_speaker_gain_in_combo(adev, snd_device, false);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001302 } else {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001303 audio_route_reset_and_update_path(adev->audio_route, device_name);
Lior Barenboim0b61bc72014-05-13 13:01:37 +03001304 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07001305
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001306 if (snd_device == SND_DEVICE_OUT_BT_A2DP)
Naresh Tannirucd2353e2016-08-19 00:37:25 +05301307 audio_extn_a2dp_stop_playback();
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001308 else if (snd_device == SND_DEVICE_IN_BT_A2DP)
Florian Pfister1a84f312018-07-19 14:38:18 +02001309 audio_extn_a2dp_stop_capture();
Zhou Songd6d71752019-05-21 18:08:51 +08001310 else if ((snd_device == SND_DEVICE_OUT_HDMI) ||
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001311 (snd_device == SND_DEVICE_OUT_DISPLAY_PORT))
Ashish Jain81eb2a82015-05-13 10:52:34 +05301312 adev->is_channel_status_set = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001313 else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301314 adev->native_playback_enabled) {
1315 ALOGD("%s: %d: napb: disabling native mode in hardware",
1316 __func__, __LINE__);
1317 audio_route_reset_and_update_path(adev->audio_route,
1318 "true-native-mode");
1319 adev->native_playback_enabled = false;
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001320 } else if ((snd_device == SND_DEVICE_OUT_HEADPHONES) &&
Preetam Singh Ranawatb0c0dd72016-08-18 00:32:06 +05301321 adev->asrc_mode_enabled) {
1322 ALOGD("%s: %d: disabling asrc mode in hardware", __func__, __LINE__);
Preetam Singh Ranawat6a836662016-09-08 17:04:35 +05301323 disable_asrc_mode(adev);
1324 audio_route_apply_and_update_path(adev->audio_route, "hph-lowpower-mode");
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001325 } else if (((snd_device == SND_DEVICE_IN_HANDSET_6MIC) ||
Dhanalakshmi Siddaniaf4bd622019-02-27 16:28:06 +05301326 (snd_device == SND_DEVICE_IN_HANDSET_QMIC)) &&
Garmond Leunge2433c32017-09-28 21:51:22 -07001327 (audio_extn_ffv_get_stream() == adev->active_input)) {
1328 ALOGD("%s: deinit ec ref loopback", __func__);
1329 audio_extn_ffv_deinit_ec_ref_loopback(adev, snd_device);
1330 }
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001331
1332 audio_extn_utils_release_snd_device(snd_device);
1333 } else {
1334 if (platform_split_snd_device(adev->platform,
1335 snd_device,
1336 &num_devices,
1337 new_snd_devices) == 0) {
1338 for (i = 0; i < num_devices; i++) {
1339 adev->snd_dev_ref_cnt[new_snd_devices[i]]--;
1340 }
1341 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001342 }
Ravi Kumar Alamanda48c921d2013-10-29 06:07:44 -07001343
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001344 return 0;
1345}
1346
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001347/*
1348 legend:
1349 uc - existing usecase
1350 new_uc - new usecase
1351 d1, d11, d2 - SND_DEVICE enums
1352 a1, a2 - corresponding ANDROID device enums
1353 B1, B2 - backend strings
1354
1355case 1
1356 uc->dev d1 (a1) B1
1357 new_uc->dev d1 (a1), d2 (a2) B1, B2
1358
1359 resolution: disable and enable uc->dev on d1
1360
1361case 2
1362 uc->dev d1 (a1) B1
1363 new_uc->dev d11 (a1) B1
1364
1365 resolution: need to switch uc since d1 and d11 are related
1366 (e.g. speaker and voice-speaker)
1367 use ANDROID_DEVICE_OUT enums to match devices since SND_DEVICE enums may vary
1368
1369case 3
1370 uc->dev d1 (a1) B1
1371 new_uc->dev d2 (a2) B2
1372
1373 resolution: no need to switch uc
1374
1375case 4
1376 uc->dev d1 (a1) B1
1377 new_uc->dev d2 (a2) B1
1378
1379 resolution: disable enable uc-dev on d2 since backends match
1380 we cannot enable two streams on two different devices if they
1381 share the same backend. e.g. if offload is on speaker device using
1382 QUAD_MI2S backend and a low-latency stream is started on voice-handset
1383 using the same backend, offload must also be switched to voice-handset.
1384
1385case 5
1386 uc->dev d1 (a1) B1
1387 new_uc->dev d1 (a1), d2 (a2) B1
1388
1389 resolution: disable enable uc-dev on d2 since backends match
1390 we cannot enable two streams on two different devices if they
1391 share the same backend.
1392
1393case 6
1394 uc->dev d1 (a1) B1
1395 new_uc->dev d2 (a1) B2
1396
1397 resolution: no need to switch
1398
1399case 7
1400 uc->dev d1 (a1), d2 (a2) B1, B2
1401 new_uc->dev d1 (a1) B1
1402
1403 resolution: no need to switch
1404
Zhou Song4ba65882018-07-09 14:48:07 +08001405case 8
1406 uc->dev d1 (a1) B1
1407 new_uc->dev d11 (a1), d2 (a2) B1, B2
1408 resolution: compared to case 1, for this case, d1 and d11 are related
1409 then need to do the same as case 2 to siwtch to new uc
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001410*/
1411static snd_device_t derive_playback_snd_device(void * platform,
1412 struct audio_usecase *uc,
1413 struct audio_usecase *new_uc,
1414 snd_device_t new_snd_device)
1415{
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301416 audio_devices_t a1, a2;
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001417
1418 snd_device_t d1 = uc->out_snd_device;
1419 snd_device_t d2 = new_snd_device;
1420
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301421 switch (uc->type) {
Surendar Karka93cd25a2018-08-28 14:21:37 +05301422 case TRANSCODE_LOOPBACK_RX :
Siddartha Shaik31b530e2017-05-19 15:26:33 +05301423 a1 = uc->stream.inout->out_config.devices;
1424 a2 = new_uc->stream.inout->out_config.devices;
1425 break;
1426 default :
1427 a1 = uc->stream.out->devices;
1428 a2 = new_uc->stream.out->devices;
1429 break;
1430 }
1431
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001432 // Treat as a special case when a1 and a2 are not disjoint
1433 if ((a1 != a2) && (a1 & a2)) {
1434 snd_device_t d3[2];
1435 int num_devices = 0;
1436 int ret = platform_split_snd_device(platform,
1437 popcount(a1) > 1 ? d1 : d2,
1438 &num_devices,
1439 d3);
1440 if (ret < 0) {
1441 if (ret != -ENOSYS) {
1442 ALOGW("%s failed to split snd_device %d",
1443 __func__,
1444 popcount(a1) > 1 ? d1 : d2);
1445 }
1446 goto end;
1447 }
1448
1449 // NB: case 7 is hypothetical and isn't a practical usecase yet.
1450 // But if it does happen, we need to give priority to d2 if
1451 // the combo devices active on the existing usecase share a backend.
1452 // This is because we cannot have a usecase active on a combo device
1453 // and a new usecase requests one device in this combo pair.
1454 if (platform_check_backends_match(d3[0], d3[1])) {
1455 return d2; // case 5
1456 } else {
Garmond Leungb9eeba42018-09-18 11:10:41 -07001457 // check if d1 is related to any of d3's
1458 if (d1 == d3[0] || d1 == d3[1])
Zhou Song4ba65882018-07-09 14:48:07 +08001459 return d1; // case 1
1460 else
1461 return d3[1]; // case 8
Haynes Mathew Georgebfe8ff42016-09-22 17:38:16 -07001462 }
1463 } else {
1464 if (platform_check_backends_match(d1, d2)) {
1465 return d2; // case 2, 4
1466 } else {
1467 return d1; // case 6, 3
1468 }
1469 }
1470
1471end:
1472 return d2; // return whatever was calculated before.
1473}
1474
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001475static void check_usecases_codec_backend(struct audio_device *adev,
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301476 struct audio_usecase *uc_info,
1477 snd_device_t snd_device)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001478{
1479 struct listnode *node;
1480 struct audio_usecase *usecase;
1481 bool switch_device[AUDIO_USECASE_MAX];
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301482 snd_device_t uc_derive_snd_device;
1483 snd_device_t derive_snd_device[AUDIO_USECASE_MAX];
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001484 snd_device_t split_snd_devices[SND_DEVICE_OUT_END];
1485 int i, num_uc_to_switch = 0, num_devices = 0;
kunleiz5cd52b82016-11-07 17:22:52 +08001486 int status = 0;
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301487 bool force_restart_session = false;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001488 /*
1489 * This function is to make sure that all the usecases that are active on
1490 * the hardware codec backend are always routed to any one device that is
1491 * handled by the hardware codec.
1492 * For example, if low-latency and deep-buffer usecases are currently active
1493 * on speaker and out_set_parameters(headset) is received on low-latency
1494 * output, then we have to make sure deep-buffer is also switched to headset,
1495 * because of the limitation that both the devices cannot be enabled
1496 * at the same time as they share the same backend.
1497 */
Mingming Yin3ee55c62014-08-04 14:23:35 -07001498 /*
1499 * This call is to check if we need to force routing for a particular stream
1500 * If there is a backend configuration change for the device when a
1501 * new stream starts, then ADM needs to be closed and re-opened with the new
1502 * configuraion. This call check if we need to re-route all the streams
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001503 * associated with the backend. Touch tone + 24 bit + native playback.
Mingming Yin3ee55c62014-08-04 14:23:35 -07001504 */
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001505 bool force_routing = platform_check_and_set_codec_backend_cfg(adev, uc_info,
1506 snd_device);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05301507 /* For a2dp device reconfigure all active sessions
1508 * with new AFE encoder format based on a2dp state
1509 */
1510 if ((SND_DEVICE_OUT_BT_A2DP == snd_device ||
1511 SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP == snd_device) &&
1512 audio_extn_a2dp_is_force_device_switch()) {
1513 force_routing = true;
1514 force_restart_session = true;
1515 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301516 ALOGD("%s:becf: force routing %d", __func__, force_routing);
1517
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001518 /* Disable all the usecases on the shared backend other than the
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001519 * specified usecase.
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08001520 */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001521 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1522 switch_device[i] = false;
1523
1524 list_for_each(node, &adev->usecase_list) {
1525 usecase = node_to_item(node, struct audio_usecase, list);
Apoorv Raghuvanshi21492162015-02-19 18:19:36 -08001526
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301527 ALOGD("%s:becf: (%d) check_usecases curr device: %s, usecase device:%s "
1528 "backends match %d",__func__, i,
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301529 platform_get_snd_device_name(snd_device),
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301530 platform_get_snd_device_name(usecase->out_snd_device),
1531 platform_check_backends_match(snd_device, usecase->out_snd_device));
Ashish Jain6a65b352017-03-21 17:24:40 +05301532 if ((usecase->type != PCM_CAPTURE) && (usecase != uc_info)) {
1533 uc_derive_snd_device = derive_playback_snd_device(adev->platform,
1534 usecase, uc_info, snd_device);
1535 if (((uc_derive_snd_device != usecase->out_snd_device) || force_routing) &&
1536 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
1537 (usecase->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) ||
1538 (usecase->devices & AUDIO_DEVICE_OUT_USB_DEVICE) ||
Garmond Leung2fd4f122018-06-02 16:04:53 -07001539 (usecase->devices & AUDIO_DEVICE_OUT_USB_HEADSET) ||
Ashish Jain6a65b352017-03-21 17:24:40 +05301540 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP) ||
1541 (usecase->devices & AUDIO_DEVICE_OUT_ALL_SCO)) &&
1542 ((force_restart_session) ||
1543 (platform_check_backends_match(snd_device, usecase->out_snd_device)))) {
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301544 ALOGD("%s:becf: check_usecases (%s) is active on (%s) - disabling ..",
1545 __func__, use_case_table[usecase->id],
1546 platform_get_snd_device_name(usecase->out_snd_device));
1547 disable_audio_route(adev, usecase);
1548 switch_device[usecase->id] = true;
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301549 /* Enable existing usecase on derived playback device */
1550 derive_snd_device[usecase->id] = uc_derive_snd_device;
Sidipotu Ashok9f0b16e2016-04-28 13:48:28 +05301551 num_uc_to_switch++;
Ashish Jain6a65b352017-03-21 17:24:40 +05301552 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001553 }
1554 }
1555
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301556 ALOGD("%s:becf: check_usecases num.of Usecases to switch %d", __func__,
1557 num_uc_to_switch);
1558
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001559 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001560 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001561
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301562 /* Make sure the previous devices to be disabled first and then enable the
1563 selected devices */
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001564 list_for_each(node, &adev->usecase_list) {
1565 usecase = node_to_item(node, struct audio_usecase, list);
1566 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001567 /* Check if output sound device to be switched can be split and if any
1568 of the split devices match with derived sound device */
1569 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1570 &num_devices, split_snd_devices) == 0) {
1571 adev->snd_dev_ref_cnt[usecase->out_snd_device]--;
1572 for (i = 0; i < num_devices; i++) {
1573 /* Disable devices that do not match with derived sound device */
1574 if (split_snd_devices[i] != derive_snd_device[usecase->id])
1575 disable_snd_device(adev, split_snd_devices[i]);
1576 }
1577 } else {
1578 disable_snd_device(adev, usecase->out_snd_device);
1579 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001580 }
1581 }
1582
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001583 list_for_each(node, &adev->usecase_list) {
1584 usecase = node_to_item(node, struct audio_usecase, list);
1585 if (switch_device[usecase->id]) {
Weiyin Jiang0d84c8e2019-04-09 22:59:54 +08001586 if (platform_split_snd_device(adev->platform, usecase->out_snd_device,
1587 &num_devices, split_snd_devices) == 0) {
1588 /* Enable derived sound device only if it does not match with
1589 one of the split sound devices. This is because the matching
1590 sound device was not disabled */
1591 bool should_enable = true;
1592 for (i = 0; i < num_devices; i++) {
1593 if (derive_snd_device[usecase->id] == split_snd_devices[i]) {
1594 should_enable = false;
1595 break;
1596 }
1597 }
1598 if (should_enable)
1599 enable_snd_device(adev, derive_snd_device[usecase->id]);
1600 } else {
1601 enable_snd_device(adev, derive_snd_device[usecase->id]);
1602 }
Krishnankutty Kolathappillydc4f7572013-11-01 20:07:13 -07001603 }
1604 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001605
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001606 /* Re-route all the usecases on the shared backend other than the
1607 specified usecase to new snd devices */
1608 list_for_each(node, &adev->usecase_list) {
1609 usecase = node_to_item(node, struct audio_usecase, list);
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301610 /* Update the out_snd_device only before enabling the audio route */
1611 if (switch_device[usecase->id]) {
Chaithanya Krishna Bacharaju49e7db02017-03-14 11:57:26 +05301612 usecase->out_snd_device = derive_snd_device[usecase->id];
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301613 if (usecase->type != VOICE_CALL) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301614 ALOGD("%s:becf: enabling usecase (%s) on (%s)", __func__,
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301615 use_case_table[usecase->id],
1616 platform_get_snd_device_name(usecase->out_snd_device));
kunleiz5cd52b82016-11-07 17:22:52 +08001617 /* Update voc calibration before enabling VoIP route */
1618 if (usecase->type == VOIP_CALL)
1619 status = platform_switch_voice_call_device_post(adev->platform,
1620 usecase->out_snd_device,
kunleizab514ca2017-01-09 14:59:50 +08001621 platform_get_input_snd_device(adev->platform, uc_info->devices));
Avinash Vaish71a8b972014-07-24 15:36:33 +05301622 enable_audio_route(adev, usecase);
Sujin Panicker390724d2019-04-26 10:43:36 +05301623 if (usecase->stream.out && usecase->id == USECASE_AUDIO_PLAYBACK_VOIP) {
kunleiz46c47dd2018-03-19 16:28:09 +08001624 out_set_voip_volume(&usecase->stream.out->stream,
1625 usecase->stream.out->volume_l,
1626 usecase->stream.out->volume_r);
1627 }
Karthik Reddy Katta3abfee22016-02-23 10:55:27 +05301628 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001629 }
1630 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001631 }
1632}
1633
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301634static void check_usecases_capture_codec_backend(struct audio_device *adev,
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001635 struct audio_usecase *uc_info,
1636 snd_device_t snd_device)
1637{
1638 struct listnode *node;
1639 struct audio_usecase *usecase;
1640 bool switch_device[AUDIO_USECASE_MAX];
1641 int i, num_uc_to_switch = 0;
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301642 int backend_check_cond = AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND;
kunleiz5cd52b82016-11-07 17:22:52 +08001643 int status = 0;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001644
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301645 bool force_routing = platform_check_and_set_capture_codec_backend_cfg(adev, uc_info,
1646 snd_device);
1647 ALOGD("%s:becf: force routing %d", __func__, force_routing);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301648
1649 /*
1650 * Make sure out devices is checked against out codec backend device and
1651 * also in devices against in codec backend. Checking out device against in
1652 * codec backend or vice versa causes issues.
1653 */
1654 if (uc_info->type == PCM_CAPTURE)
1655 backend_check_cond = AUDIO_DEVICE_IN_ALL_CODEC_BACKEND;
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001656 /*
1657 * This function is to make sure that all the active capture usecases
1658 * are always routed to the same input sound device.
1659 * For example, if audio-record and voice-call usecases are currently
1660 * active on speaker(rx) and speaker-mic (tx) and out_set_parameters(earpiece)
1661 * is received for voice call then we have to make sure that audio-record
1662 * usecase is also switched to earpiece i.e. voice-dmic-ef,
1663 * because of the limitation that two devices cannot be enabled
1664 * at the same time if they share the same backend.
1665 */
1666 for (i = 0; i < AUDIO_USECASE_MAX; i++)
1667 switch_device[i] = false;
1668
1669 list_for_each(node, &adev->usecase_list) {
1670 usecase = node_to_item(node, struct audio_usecase, list);
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301671 /*
1672 * TODO: Enhance below condition to handle BT sco/USB multi recording
1673 */
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001674 if (usecase->type != PCM_PLAYBACK &&
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001675 usecase != uc_info &&
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05301676 (usecase->in_snd_device != snd_device || force_routing) &&
Dhanalakshmi Siddanib678a802016-12-03 11:51:41 +05301677 ((uc_info->devices & backend_check_cond) &&
Karthik Reddy Katta0d471762015-08-20 13:36:07 +05301678 (((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND) ||
Satya Krishna Pindiproli458b5a72017-03-13 15:14:24 +05301679 (usecase->type == VOIP_CALL))) &&
Carter Hsu1d2a0532018-10-04 09:24:36 +08001680 ((uc_info->type == VOICE_CALL &&
1681 usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL) ||
1682 platform_check_backends_match(snd_device,\
1683 usecase->in_snd_device)) &&
Anish Kumara020a7c2014-10-17 11:13:22 -07001684 (usecase->id != USECASE_AUDIO_SPKR_CALIB_TX)) {
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001685 ALOGV("%s: Usecase (%s) is active on (%s) - disabling ..",
1686 __func__, use_case_table[usecase->id],
Devin Kim1e5f3532013-08-09 07:48:29 -07001687 platform_get_snd_device_name(usecase->in_snd_device));
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001688 disable_audio_route(adev, usecase);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001689 switch_device[usecase->id] = true;
1690 num_uc_to_switch++;
1691 }
1692 }
1693
1694 if (num_uc_to_switch) {
Haynes Mathew Georgeef1e3d32014-04-24 11:53:44 -07001695 /* All streams have been de-routed. Disable the device */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001696
Venkata Narendra Kumar Gutta7610e632014-04-14 23:16:38 +05301697 /* Make sure the previous devices to be disabled first and then enable the
1698 selected devices */
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001699 list_for_each(node, &adev->usecase_list) {
1700 usecase = node_to_item(node, struct audio_usecase, list);
1701 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001702 disable_snd_device(adev, usecase->in_snd_device);
Shiv Maliyappanahalli80ac6282013-12-20 18:56:15 -08001703 }
1704 }
1705
1706 list_for_each(node, &adev->usecase_list) {
1707 usecase = node_to_item(node, struct audio_usecase, list);
1708 if (switch_device[usecase->id]) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07001709 enable_snd_device(adev, snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001710 }
1711 }
1712
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001713 /* Re-route all the usecases on the shared backend other than the
1714 specified usecase to new snd devices */
1715 list_for_each(node, &adev->usecase_list) {
1716 usecase = node_to_item(node, struct audio_usecase, list);
1717 /* Update the in_snd_device only before enabling the audio route */
1718 if (switch_device[usecase->id] ) {
1719 usecase->in_snd_device = snd_device;
kunleiz5cd52b82016-11-07 17:22:52 +08001720 if (usecase->type != VOICE_CALL) {
1721 /* Update voc calibration before enabling VoIP route */
1722 if (usecase->type == VOIP_CALL)
1723 status = platform_switch_voice_call_device_post(adev->platform,
Zhou Song557e7282017-05-05 17:18:18 +08001724 platform_get_output_snd_device(adev->platform, uc_info->stream.out),
kunleiz5cd52b82016-11-07 17:22:52 +08001725 usecase->in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05301726 enable_audio_route(adev, usecase);
kunleiz5cd52b82016-11-07 17:22:52 +08001727 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001728 }
1729 }
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07001730 }
1731}
1732
Mingming Yin3a941d42016-02-17 18:08:05 -08001733static void reset_hdmi_sink_caps(struct stream_out *out) {
1734 int i = 0;
1735
1736 for (i = 0; i<= MAX_SUPPORTED_CHANNEL_MASKS; i++) {
1737 out->supported_channel_masks[i] = 0;
1738 }
1739 for (i = 0; i<= MAX_SUPPORTED_FORMATS; i++) {
1740 out->supported_formats[i] = 0;
1741 }
1742 for (i = 0; i<= MAX_SUPPORTED_SAMPLE_RATES; i++) {
1743 out->supported_sample_rates[i] = 0;
1744 }
1745}
1746
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001747/* must be called with hw device mutex locked */
Mingming Yin3a941d42016-02-17 18:08:05 -08001748static int read_hdmi_sink_caps(struct stream_out *out)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001749{
Mingming Yin3a941d42016-02-17 18:08:05 -08001750 int ret = 0, i = 0, j = 0;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07001751 int channels = platform_edid_get_max_channels(out->dev->platform);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001752
Mingming Yin3a941d42016-02-17 18:08:05 -08001753 reset_hdmi_sink_caps(out);
1754
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001755 /* Cache ext disp type */
Garmond Leung37850ab2016-10-06 11:42:18 -07001756 if (platform_get_ext_disp_type(adev->platform) <= 0) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001757 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Garmond Leung37850ab2016-10-06 11:42:18 -07001758 return -EINVAL;
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07001759 }
1760
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001761 switch (channels) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001762 case 8:
Mingming Yin3a941d42016-02-17 18:08:05 -08001763 ALOGV("%s: HDMI supports 7.1 channels", __func__);
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07001764 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_7POINT1;
Mingming Yin3a941d42016-02-17 18:08:05 -08001765 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_6POINT1;
1766 case 6:
1767 ALOGV("%s: HDMI supports 5.1 channels", __func__);
1768 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_5POINT1;
1769 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_PENTA;
1770 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_QUAD;
1771 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_SURROUND;
1772 out->supported_channel_masks[i++] = AUDIO_CHANNEL_OUT_2POINT1;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001773 break;
1774 default:
Mingming Yin3a941d42016-02-17 18:08:05 -08001775 ALOGE("invalid/nonstandard channal count[%d]",channels);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001776 ret = -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001777 break;
1778 }
Mingming Yin3a941d42016-02-17 18:08:05 -08001779
1780 // check channel format caps
1781 i = 0;
1782 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_AC3)) {
1783 ALOGV(":%s HDMI supports AC3/EAC3 formats", __func__);
1784 out->supported_formats[i++] = AUDIO_FORMAT_AC3;
1785 //Adding EAC3/EAC3_JOC formats if AC3 is supported by the sink.
1786 //EAC3/EAC3_JOC will be converted to AC3 for decoding if needed
1787 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3;
1788 out->supported_formats[i++] = AUDIO_FORMAT_E_AC3_JOC;
1789 }
1790
Ben Romberger1aaaf862017-04-06 17:49:46 -07001791 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DOLBY_TRUEHD)) {
1792 ALOGV(":%s HDMI supports TRUE HD format", __func__);
1793 out->supported_formats[i++] = AUDIO_FORMAT_DOLBY_TRUEHD;
1794 }
1795
Mingming Yin3a941d42016-02-17 18:08:05 -08001796 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS)) {
1797 ALOGV(":%s HDMI supports DTS format", __func__);
1798 out->supported_formats[i++] = AUDIO_FORMAT_DTS;
1799 }
1800
1801 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_DTS_HD)) {
1802 ALOGV(":%s HDMI supports DTS HD format", __func__);
1803 out->supported_formats[i++] = AUDIO_FORMAT_DTS_HD;
1804 }
1805
Naresh Tanniru928f0862017-04-07 16:44:23 -07001806 if (platform_is_edid_supported_format(out->dev->platform, AUDIO_FORMAT_IEC61937)) {
1807 ALOGV(":%s HDMI supports IEC61937 format", __func__);
1808 out->supported_formats[i++] = AUDIO_FORMAT_IEC61937;
1809 }
1810
Mingming Yin3a941d42016-02-17 18:08:05 -08001811
1812 // check sample rate caps
1813 i = 0;
1814 for (j = 0; j < MAX_SUPPORTED_SAMPLE_RATES; j++) {
1815 if (platform_is_edid_supported_sample_rate(out->dev->platform, out_hdmi_sample_rates[j])) {
1816 ALOGV(":%s HDMI supports sample rate:%d", __func__, out_hdmi_sample_rates[j]);
1817 out->supported_sample_rates[i++] = out_hdmi_sample_rates[j];
1818 }
1819 }
1820
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07001821 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08001822}
1823
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001824static inline ssize_t read_usb_sup_sample_rates(bool is_playback __unused,
1825 uint32_t *supported_sample_rates __unused,
1826 uint32_t max_rates __unused)
1827{
1828 ssize_t count = audio_extn_usb_get_sup_sample_rates(is_playback,
1829 supported_sample_rates,
1830 max_rates);
Ashish Jain4847e9d2017-08-17 19:16:57 +05301831 ssize_t i = 0;
1832
1833 for (i=0; i<count; i++) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001834 ALOGV("%s %s %d", __func__, is_playback ? "P" : "C",
1835 supported_sample_rates[i]);
1836 }
1837 return count;
1838}
1839
1840static inline int read_usb_sup_channel_masks(bool is_playback,
1841 audio_channel_mask_t *supported_channel_masks,
1842 uint32_t max_masks)
1843{
1844 int channels = audio_extn_usb_get_max_channels(is_playback);
1845 int channel_count;
1846 uint32_t num_masks = 0;
1847 if (channels > MAX_HIFI_CHANNEL_COUNT)
1848 channels = MAX_HIFI_CHANNEL_COUNT;
1849
1850 if (is_playback) {
Eric Laurent68a87112019-05-01 18:07:29 -07001851 // start from 2 channels as framework currently doesn't support mono.
1852 if (channels >= FCC_2) {
1853 supported_channel_masks[num_masks++] = audio_channel_out_mask_from_count(FCC_2);
1854 }
1855 for (channel_count = FCC_2;
1856 channel_count <= channels && num_masks < max_masks;
1857 ++channel_count) {
1858 supported_channel_masks[num_masks++] =
1859 audio_channel_mask_for_index_assignment_from_count(channel_count);
1860 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001861 } else {
vincenttewf51c94e2019-05-07 10:28:53 +08001862 // For capture we report all supported channel masks from 1 channel up.
1863 channel_count = MIN_CHANNEL_COUNT;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001864 // audio_channel_in_mask_from_count() does the right conversion to either positional or
1865 // indexed mask
Eric Laurent68a87112019-05-01 18:07:29 -07001866 for ( ; channel_count <= channels && num_masks < max_masks; channel_count++) {
1867 audio_channel_mask_t mask = AUDIO_CHANNEL_NONE;
1868 if (channel_count <= FCC_2) {
1869 mask = audio_channel_in_mask_from_count(channel_count);
1870 supported_channel_masks[num_masks++] = mask;
1871 }
1872 const audio_channel_mask_t index_mask =
1873 audio_channel_mask_for_index_assignment_from_count(channel_count);
1874 if (mask != index_mask && num_masks < max_masks) { // ensure index mask added.
1875 supported_channel_masks[num_masks++] = index_mask;
1876 }
1877 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001878 }
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301879
vincenttewf51c94e2019-05-07 10:28:53 +08001880 for (size_t i = 0; i < num_masks; ++i) {
1881 ALOGV("%s: %s supported ch %d supported_channel_masks[%zu] %08x num_masks %d", __func__,
1882 is_playback ? "P" : "C", channels, i, supported_channel_masks[i], num_masks);
Lakshman Chaluvarajub79fafd2018-11-21 10:24:37 +05301883 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07001884 return num_masks;
1885}
1886
1887static inline int read_usb_sup_formats(bool is_playback __unused,
1888 audio_format_t *supported_formats,
1889 uint32_t max_formats __unused)
1890{
1891 int bitwidth = audio_extn_usb_get_max_bit_width(is_playback);
1892 switch (bitwidth) {
1893 case 24:
1894 // XXX : usb.c returns 24 for s24 and s24_le?
1895 supported_formats[0] = AUDIO_FORMAT_PCM_24_BIT_PACKED;
1896 break;
1897 case 32:
1898 supported_formats[0] = AUDIO_FORMAT_PCM_32_BIT;
1899 break;
1900 case 16:
1901 default :
1902 supported_formats[0] = AUDIO_FORMAT_PCM_16_BIT;
1903 break;
1904 }
1905 ALOGV("%s: %s supported format %d", __func__,
1906 is_playback ? "P" : "C", bitwidth);
1907 return 1;
1908}
1909
1910static inline int read_usb_sup_params_and_compare(bool is_playback,
1911 audio_format_t *format,
1912 audio_format_t *supported_formats,
1913 uint32_t max_formats,
1914 audio_channel_mask_t *mask,
1915 audio_channel_mask_t *supported_channel_masks,
1916 uint32_t max_masks,
1917 uint32_t *rate,
1918 uint32_t *supported_sample_rates,
1919 uint32_t max_rates) {
1920 int ret = 0;
1921 int num_formats;
1922 int num_masks;
1923 int num_rates;
1924 int i;
1925
1926 num_formats = read_usb_sup_formats(is_playback, supported_formats,
1927 max_formats);
1928 num_masks = read_usb_sup_channel_masks(is_playback, supported_channel_masks,
1929 max_masks);
1930
1931 num_rates = read_usb_sup_sample_rates(is_playback,
1932 supported_sample_rates, max_rates);
1933
1934#define LUT(table, len, what, dflt) \
1935 for (i=0; i<len && (table[i] != what); i++); \
1936 if (i==len) { ret |= (what == dflt ? 0 : -1); what=table[0]; }
1937
1938 LUT(supported_formats, num_formats, *format, AUDIO_FORMAT_DEFAULT);
1939 LUT(supported_channel_masks, num_masks, *mask, AUDIO_CHANNEL_NONE);
1940 LUT(supported_sample_rates, num_rates, *rate, 0);
1941
1942#undef LUT
1943 return ret < 0 ? -EINVAL : 0; // HACK TBD
1944}
1945
Alexy Josephb1379942016-01-29 15:49:38 -08001946audio_usecase_t get_usecase_id_from_usecase_type(const struct audio_device *adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001947 usecase_type_t type)
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001948{
1949 struct audio_usecase *usecase;
1950 struct listnode *node;
1951
1952 list_for_each(node, &adev->usecase_list) {
1953 usecase = node_to_item(node, struct audio_usecase, list);
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08001954 if (usecase->type == type) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001955 ALOGV("%s: usecase id %d", __func__, usecase->id);
1956 return usecase->id;
1957 }
1958 }
1959 return USECASE_INVALID;
1960}
1961
Alexy Josephb1379942016-01-29 15:49:38 -08001962struct audio_usecase *get_usecase_from_list(const struct audio_device *adev,
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07001963 audio_usecase_t uc_id)
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07001964{
1965 struct audio_usecase *usecase;
1966 struct listnode *node;
1967
1968 list_for_each(node, &adev->usecase_list) {
1969 usecase = node_to_item(node, struct audio_usecase, list);
1970 if (usecase->id == uc_id)
1971 return usecase;
1972 }
1973 return NULL;
1974}
1975
Dhananjay Kumard4833242016-10-06 22:09:12 +05301976struct stream_in *get_next_active_input(const struct audio_device *adev)
1977{
1978 struct audio_usecase *usecase;
1979 struct listnode *node;
1980
1981 list_for_each_reverse(node, &adev->usecase_list) {
1982 usecase = node_to_item(node, struct audio_usecase, list);
1983 if (usecase->type == PCM_CAPTURE)
1984 return usecase->stream.in;
1985 }
1986 return NULL;
1987}
1988
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05301989/*
1990 * is a true native playback active
1991 */
1992bool audio_is_true_native_stream_active(struct audio_device *adev)
1993{
1994 bool active = false;
1995 int i = 0;
1996 struct listnode *node;
1997
1998 if (NATIVE_AUDIO_MODE_TRUE_44_1 != platform_get_native_support()) {
1999 ALOGV("%s:napb: not in true mode or non hdphones device",
2000 __func__);
2001 active = false;
2002 goto exit;
2003 }
2004
2005 list_for_each(node, &adev->usecase_list) {
2006 struct audio_usecase *uc;
2007 uc = node_to_item(node, struct audio_usecase, list);
2008 struct stream_out *curr_out =
2009 (struct stream_out*) uc->stream.out;
2010
2011 if (curr_out && PCM_PLAYBACK == uc->type) {
2012 ALOGD("%s:napb: (%d) (%s)id (%d) sr %d bw "
2013 "(%d) device %s", __func__, i++, use_case_table[uc->id],
2014 uc->id, curr_out->sample_rate,
2015 curr_out->bit_width,
2016 platform_get_snd_device_name(uc->out_snd_device));
2017
2018 if (is_offload_usecase(uc->id) &&
2019 (curr_out->sample_rate == OUTPUT_SAMPLING_RATE_44100)) {
2020 active = true;
2021 ALOGD("%s:napb:native stream detected", __func__);
2022 }
2023 }
2024 }
2025exit:
2026 return active;
2027}
2028
Xiaojun Sang785b5da2017-08-03 15:52:29 +08002029uint32_t adev_get_dsp_bit_width_enforce_mode()
2030{
2031 if (adev == NULL) {
2032 ALOGE("%s: adev is null. Disable DSP bit width enforce mode.\n", __func__);
2033 return 0;
2034 }
2035 return adev->dsp_bit_width_enforce_mode;
2036}
2037
2038static uint32_t adev_init_dsp_bit_width_enforce_mode(struct mixer *mixer)
2039{
2040 char value[PROPERTY_VALUE_MAX];
2041 int trial;
2042 uint32_t dsp_bit_width_enforce_mode = 0;
2043
2044 if (!mixer) {
2045 ALOGE("%s: adev mixer is null. cannot update DSP bitwidth.\n",
2046 __func__);
2047 return 0;
2048 }
2049
2050 if (property_get("persist.vendor.audio_hal.dsp_bit_width_enforce_mode",
2051 value, NULL) > 0) {
2052 trial = atoi(value);
2053 switch (trial) {
2054 case 16:
2055 dsp_bit_width_enforce_mode = 16;
2056 break;
2057 case 24:
2058 dsp_bit_width_enforce_mode = 24;
2059 break;
2060 case 32:
2061 dsp_bit_width_enforce_mode = 32;
2062 break;
2063 default:
2064 dsp_bit_width_enforce_mode = 0;
2065 ALOGD("%s Dynamic DSP bitwidth config is disabled.", __func__);
2066 break;
2067 }
2068 }
2069
2070 return dsp_bit_width_enforce_mode;
2071}
2072
2073static void audio_enable_asm_bit_width_enforce_mode(struct mixer *mixer,
2074 uint32_t enforce_mode,
2075 bool enable)
2076{
2077 struct mixer_ctl *ctl = NULL;
2078 const char *mixer_ctl_name = "ASM Bit Width";
2079 uint32_t asm_bit_width_mode = 0;
2080
2081 if (enforce_mode == 0) {
2082 ALOGD("%s: DSP bitwidth feature is disabled.", __func__);
2083 return;
2084 }
2085
2086 ctl = mixer_get_ctl_by_name(mixer, mixer_ctl_name);
2087 if (!ctl) {
2088 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2089 __func__, mixer_ctl_name);
2090 return;
2091 }
2092
2093 if (enable)
2094 asm_bit_width_mode = enforce_mode;
2095 else
2096 asm_bit_width_mode = 0;
2097
2098 ALOGV("%s DSP bit width feature status is %d width=%d",
2099 __func__, enable, asm_bit_width_mode);
2100 if (mixer_ctl_set_value(ctl, 0, asm_bit_width_mode) < 0)
2101 ALOGE("%s: Could not set ASM biwidth %d", __func__,
2102 asm_bit_width_mode);
2103
2104 return;
2105}
2106
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302107/*
2108 * if native DSD playback active
2109 */
2110bool audio_is_dsd_native_stream_active(struct audio_device *adev)
2111{
2112 bool active = false;
2113 struct listnode *node = NULL;
2114 struct audio_usecase *uc = NULL;
2115 struct stream_out *curr_out = NULL;
2116
2117 list_for_each(node, &adev->usecase_list) {
2118 uc = node_to_item(node, struct audio_usecase, list);
2119 curr_out = (struct stream_out*) uc->stream.out;
2120
2121 if (curr_out && PCM_PLAYBACK == uc->type &&
2122 (DSD_NATIVE_BACKEND == platform_get_backend_index(uc->out_snd_device))) {
2123 active = true;
2124 ALOGV("%s:DSD playback is active", __func__);
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05302125 break;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05302126 }
2127 }
2128 return active;
2129}
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302130
2131static bool force_device_switch(struct audio_usecase *usecase)
2132{
2133 bool ret = false;
2134 bool is_it_true_mode = false;
2135
Zhou Song30f2c3e2018-02-08 14:02:15 +08002136 if (usecase->type == PCM_CAPTURE ||
Surendar Karka93cd25a2018-08-28 14:21:37 +05302137 usecase->type == TRANSCODE_LOOPBACK_RX ||
2138 usecase->type == TRANSCODE_LOOPBACK_TX) {
Zhou Song30f2c3e2018-02-08 14:02:15 +08002139 return false;
2140 }
2141
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002142 if(usecase->stream.out == NULL) {
2143 ALOGE("%s: stream.out is NULL", __func__);
2144 return false;
2145 }
2146
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302147 if (is_offload_usecase(usecase->id) &&
Xiaojun Sang869f2012016-02-23 16:33:07 +08002148 (usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) &&
2149 (usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADSET ||
2150 usecase->stream.out->devices == AUDIO_DEVICE_OUT_WIRED_HEADPHONE)) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302151 is_it_true_mode = (NATIVE_AUDIO_MODE_TRUE_44_1 == platform_get_native_support()? true : false);
2152 if ((is_it_true_mode && !adev->native_playback_enabled) ||
2153 (!is_it_true_mode && adev->native_playback_enabled)){
2154 ret = true;
2155 ALOGD("napb: time to toggle native mode");
2156 }
2157 }
2158
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302159 // Force all a2dp output devices to reconfigure for proper AFE encode format
Ashish Jainc597d102016-12-12 10:31:34 +05302160 //Also handle a case where in earlier a2dp start failed as A2DP stream was
2161 //in suspended state, hence try to trigger a retry when we again get a routing request.
Aalique Grahamecbc46a22017-10-05 10:30:23 -07002162 if((usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Ashish Jainc597d102016-12-12 10:31:34 +05302163 audio_extn_a2dp_is_force_device_switch()) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302164 ALOGD("Force a2dp device switch to update new encoder config");
2165 ret = true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002166 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05302167
Florian Pfister1a84f312018-07-19 14:38:18 +02002168 if (usecase->stream.out->stream_config_changed) {
Manish Dewangan671a4202017-08-18 17:30:46 +05302169 ALOGD("Force stream_config_changed to update iec61937 transmission config");
2170 return true;
Florian Pfister1a84f312018-07-19 14:38:18 +02002171 }
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302172 return ret;
2173}
2174
Aalique Grahame22e49102018-12-18 14:23:57 -08002175static void stream_app_type_cfg_init(struct stream_app_type_cfg *cfg)
2176{
2177 cfg->gain[0] = cfg->gain[1] = APP_TYPE_GAIN_DEFAULT;
2178}
2179
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302180bool is_btsco_device(snd_device_t out_snd_device, snd_device_t in_snd_device)
2181{
2182 bool ret=false;
2183 if ((out_snd_device == SND_DEVICE_OUT_BT_SCO ||
2184 out_snd_device == SND_DEVICE_OUT_BT_SCO_WB) ||
2185 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB_NREC ||
2186 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_WB ||
2187 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC_NREC ||
2188 in_snd_device == SND_DEVICE_IN_BT_SCO_MIC)
2189 ret = true;
2190
2191 return ret;
2192}
2193
2194bool is_a2dp_device(snd_device_t out_snd_device)
2195{
2196 bool ret=false;
2197 if (out_snd_device == SND_DEVICE_OUT_BT_A2DP)
2198 ret = true;
2199
2200 return ret;
2201}
2202
2203bool is_bt_soc_on(struct audio_device *adev)
2204{
2205 struct mixer_ctl *ctl;
2206 char *mixer_ctl_name = "BT SOC status";
2207 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
2208 bool bt_soc_status = true;
2209 if (!ctl) {
2210 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2211 __func__, mixer_ctl_name);
2212 /*This is to ensure we dont break targets which dont have the kernel change*/
2213 return true;
2214 }
2215 bt_soc_status = mixer_ctl_get_value(ctl, 0);
2216 ALOGD("BT SOC status: %d",bt_soc_status);
2217 return bt_soc_status;
2218}
2219
2220int out_standby_l(struct audio_stream *stream);
2221
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002222int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002223{
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002224 snd_device_t out_snd_device = SND_DEVICE_NONE;
2225 snd_device_t in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002226 struct audio_usecase *usecase = NULL;
2227 struct audio_usecase *vc_usecase = NULL;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002228 struct audio_usecase *voip_usecase = NULL;
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002229 struct audio_usecase *hfp_usecase = NULL;
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302230 struct stream_out stream_out;
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002231 audio_usecase_t hfp_ucid;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002232 int status = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002233
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302234 ALOGD("%s for use case (%s)", __func__, use_case_table[uc_id]);
2235
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002236 usecase = get_usecase_from_list(adev, uc_id);
2237 if (usecase == NULL) {
2238 ALOGE("%s: Could not find the usecase(%d)", __func__, uc_id);
2239 return -EINVAL;
2240 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002241
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002242 if ((usecase->type == VOICE_CALL) ||
Vimal Puthanveed5b4d3f12013-11-05 15:57:39 -08002243 (usecase->type == VOIP_CALL) ||
2244 (usecase->type == PCM_HFP_CALL)) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302245 if(usecase->stream.out == NULL) {
2246 ALOGE("%s: stream.out is NULL", __func__);
2247 return -EINVAL;
2248 }
Eric Laurentb23d5282013-05-14 15:27:20 -07002249 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002250 usecase->stream.out);
Eric Laurentb23d5282013-05-14 15:27:20 -07002251 in_snd_device = platform_get_input_snd_device(adev->platform, usecase->stream.out->devices);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002252 usecase->devices = usecase->stream.out->devices;
Surendar Karka93cd25a2018-08-28 14:21:37 +05302253 } else if (usecase->type == TRANSCODE_LOOPBACK_RX) {
Siddartha Shaik31b530e2017-05-19 15:26:33 +05302254 if (usecase->stream.inout == NULL) {
2255 ALOGE("%s: stream.inout is NULL", __func__);
2256 return -EINVAL;
2257 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302258 stream_out.devices = usecase->stream.inout->out_config.devices;
2259 stream_out.sample_rate = usecase->stream.inout->out_config.sample_rate;
2260 stream_out.format = usecase->stream.inout->out_config.format;
2261 stream_out.channel_mask = usecase->stream.inout->out_config.channel_mask;
2262 out_snd_device = platform_get_output_snd_device(adev->platform,
2263 &stream_out);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302264 usecase->devices = out_snd_device;
2265 } else if (usecase->type == TRANSCODE_LOOPBACK_TX ) {
2266 if (usecase->stream.inout == NULL) {
2267 ALOGE("%s: stream.inout is NULL", __func__);
2268 return -EINVAL;
2269 }
Siddartha Shaik44dd7702017-06-14 12:13:25 +05302270 in_snd_device = platform_get_input_snd_device(adev->platform, AUDIO_DEVICE_NONE);
Surendar Karka93cd25a2018-08-28 14:21:37 +05302271 usecase->devices = in_snd_device;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002272 } else {
2273 /*
2274 * If the voice call is active, use the sound devices of voice call usecase
2275 * so that it would not result any device switch. All the usecases will
2276 * be switched to new device when select_devices() is called for voice call
2277 * usecase. This is to avoid switching devices for voice call when
2278 * check_usecases_codec_backend() is called below.
Alexy Joseph79dfa3c2016-04-20 18:44:56 -07002279 * choose voice call device only if the use case device is
2280 * also using the codec backend
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002281 */
Shiv Maliyappanahallibb4cf0b2016-01-21 11:30:06 -08002282 if (voice_is_in_call(adev) && adev->mode != AUDIO_MODE_NORMAL) {
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07002283 vc_usecase = get_usecase_from_list(adev,
Narsinga Rao Chellaf928a982015-03-06 14:57:35 -08002284 get_usecase_id_from_usecase_type(adev, VOICE_CALL));
Alexy Josephdbcddf22016-05-16 17:54:09 -07002285 if ((vc_usecase) && (((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2286 (usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) ||
Preetam Singh Ranawat097cb1f2016-07-19 13:49:04 +05302287 ((vc_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
2288 (usecase->devices & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) ||
juyuchen2d415992018-11-16 14:15:16 +08002289 (vc_usecase->devices == AUDIO_DEVICE_OUT_HEARING_AID) ||
2290 (usecase->devices == AUDIO_DEVICE_IN_VOICE_CALL))) {
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002291 in_snd_device = vc_usecase->in_snd_device;
2292 out_snd_device = vc_usecase->out_snd_device;
2293 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002294 } else if (voice_extn_compress_voip_is_active(adev)) {
yidongh02ef86f2017-04-21 15:36:04 +08002295 bool out_snd_device_backend_match = true;
yidongh47785a82017-05-08 19:29:29 +08002296 voip_usecase = get_usecase_from_list(adev, USECASE_COMPRESS_VOIP_CALL);
yidongh6261d8e2017-05-15 17:04:02 +08002297 if ((voip_usecase != NULL) &&
2298 (usecase->type == PCM_PLAYBACK) &&
2299 (usecase->stream.out != NULL)) {
yidongh02ef86f2017-04-21 15:36:04 +08002300 out_snd_device_backend_match = platform_check_backends_match(
2301 voip_usecase->out_snd_device,
2302 platform_get_output_snd_device(
2303 adev->platform,
2304 usecase->stream.out));
2305 }
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002306 if ((voip_usecase) && ((voip_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) &&
Zhou Song0154bf12016-08-04 10:48:16 +08002307 ((usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND) ||
2308 ((usecase->devices & ~AUDIO_DEVICE_BIT_IN) & AUDIO_DEVICE_IN_ALL_CODEC_BACKEND)) &&
yidongh02ef86f2017-04-21 15:36:04 +08002309 out_snd_device_backend_match &&
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002310 (voip_usecase->stream.out != adev->primary_output))) {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08002311 in_snd_device = voip_usecase->in_snd_device;
2312 out_snd_device = voip_usecase->out_snd_device;
2313 }
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002314 } else if (audio_extn_hfp_is_active(adev)) {
Vimal Puthanveed41fcff22014-01-23 15:56:53 -08002315 hfp_ucid = audio_extn_hfp_get_usecase();
2316 hfp_usecase = get_usecase_from_list(adev, hfp_ucid);
Mingming Yin2d8aa2e2014-08-14 00:00:51 -07002317 if ((hfp_usecase) && (hfp_usecase->devices & AUDIO_DEVICE_OUT_ALL_CODEC_BACKEND)) {
Vimal Puthanveed37b4a1c2014-01-07 16:47:47 -08002318 in_snd_device = hfp_usecase->in_snd_device;
2319 out_snd_device = hfp_usecase->out_snd_device;
2320 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002321 }
2322 if (usecase->type == PCM_PLAYBACK) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302323 if (usecase->stream.out == NULL) {
2324 ALOGE("%s: stream.out is NULL", __func__);
2325 return -EINVAL;
2326 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002327 usecase->devices = usecase->stream.out->devices;
2328 in_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002329 if (out_snd_device == SND_DEVICE_NONE) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002330 out_snd_device = platform_get_output_snd_device(adev->platform,
Apoorv Raghuvanshif59bb222015-02-18 12:23:23 -08002331 usecase->stream.out);
kunleizdcf967a2018-08-07 17:09:11 +08002332 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
kunleizb27e7952018-10-12 15:49:35 +08002333 if (voip_usecase == NULL && adev->primary_output && !adev->primary_output->standby)
kunleizdcf967a2018-08-07 17:09:11 +08002334 voip_usecase = get_usecase_from_list(adev, adev->primary_output->usecase);
2335
2336 if ((usecase->stream.out != NULL &&
2337 voip_usecase != NULL &&
2338 usecase->stream.out->usecase == voip_usecase->id) &&
2339 adev->active_input &&
Aalique Grahame22e49102018-12-18 14:23:57 -08002340 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
2341 adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
kunleizdcf967a2018-08-07 17:09:11 +08002342 out_snd_device != usecase->out_snd_device) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002343 select_devices(adev, adev->active_input->usecase);
2344 }
2345 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002346 } else if (usecase->type == PCM_CAPTURE) {
Aditya Bavanaribdda2f22016-10-19 15:02:05 +05302347 if (usecase->stream.in == NULL) {
2348 ALOGE("%s: stream.in is NULL", __func__);
2349 return -EINVAL;
2350 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002351 usecase->devices = usecase->stream.in->device;
2352 out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002353 if (in_snd_device == SND_DEVICE_NONE) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002354 audio_devices_t out_device = AUDIO_DEVICE_NONE;
Leena Winterrowd3c8fbae2016-01-12 15:05:53 -08002355 if (adev->active_input &&
2356 (adev->active_input->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Karthik Reddy Kattaf621ec72014-11-21 16:37:38 +05302357 (adev->mode == AUDIO_MODE_IN_COMMUNICATION &&
kunleizdcf967a2018-08-07 17:09:11 +08002358 adev->active_input->source == AUDIO_SOURCE_MIC))) {
2359 voip_usecase = get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP);
2360 if (voip_usecase != NULL && voip_usecase->stream.out != NULL)
2361 out_device = voip_usecase->stream.out->devices;
2362 else if (adev->primary_output && !adev->primary_output->standby)
2363 out_device = adev->primary_output->devices;
Apoorv Raghuvanshi924b3022015-07-06 15:07:14 -07002364 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002365 } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
2366 out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
juyuchen2d415992018-11-16 14:15:16 +08002367 } else {
2368 /* forcing speaker o/p device to get matching i/p pair
2369 in case o/p is not routed from same primary HAL */
2370 out_device = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002371 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002372 in_snd_device = platform_get_input_snd_device(adev->platform, out_device);
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07002373 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002374 }
2375 }
2376
2377 if (out_snd_device == usecase->out_snd_device &&
2378 in_snd_device == usecase->in_snd_device) {
Sidipotu Ashoke6f78cb2015-11-05 14:42:20 +05302379
2380 if (!force_device_switch(usecase))
2381 return 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002382 }
2383
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302384 if ((is_btsco_device(out_snd_device,in_snd_device) && !adev->bt_sco_on) ||
Florian Pfister1a84f312018-07-19 14:38:18 +02002385 (is_a2dp_device(out_snd_device) && !audio_extn_a2dp_source_is_ready())) {
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302386 ALOGD("SCO/A2DP is selected but they are not connected/ready hence dont route");
2387 return 0;
2388 }
2389
Aalique Grahame22e49102018-12-18 14:23:57 -08002390 if (out_snd_device != SND_DEVICE_NONE &&
2391 out_snd_device != adev->last_logged_snd_device[uc_id][0]) {
2392 ALOGD("%s: changing use case %s output device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2393 __func__,
2394 use_case_table[uc_id],
2395 adev->last_logged_snd_device[uc_id][0],
2396 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][0]),
2397 adev->last_logged_snd_device[uc_id][0] != SND_DEVICE_NONE ?
2398 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][0]) :
2399 -1,
2400 out_snd_device,
2401 platform_get_snd_device_name(out_snd_device),
2402 platform_get_snd_device_acdb_id(out_snd_device));
2403 adev->last_logged_snd_device[uc_id][0] = out_snd_device;
2404 }
2405 if (in_snd_device != SND_DEVICE_NONE &&
2406 in_snd_device != adev->last_logged_snd_device[uc_id][1]) {
2407 ALOGD("%s: changing use case %s input device from(%d: %s, acdb %d) to (%d: %s, acdb %d)",
2408 __func__,
2409 use_case_table[uc_id],
2410 adev->last_logged_snd_device[uc_id][1],
2411 platform_get_snd_device_name(adev->last_logged_snd_device[uc_id][1]),
2412 adev->last_logged_snd_device[uc_id][1] != SND_DEVICE_NONE ?
2413 platform_get_snd_device_acdb_id(adev->last_logged_snd_device[uc_id][1]) :
2414 -1,
2415 in_snd_device,
2416 platform_get_snd_device_name(in_snd_device),
2417 platform_get_snd_device_acdb_id(in_snd_device));
2418 adev->last_logged_snd_device[uc_id][1] = in_snd_device;
2419 }
2420
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08002421
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002422 /*
2423 * Limitation: While in call, to do a device switch we need to disable
2424 * and enable both RX and TX devices though one of them is same as current
2425 * device.
2426 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002427 if ((usecase->type == VOICE_CALL) &&
2428 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2429 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002430 status = platform_switch_voice_call_device_pre(adev->platform);
Narsinga Rao Chella116142b2015-08-14 18:00:08 -07002431 }
2432
2433 if (((usecase->type == VOICE_CALL) ||
2434 (usecase->type == VOIP_CALL)) &&
2435 (usecase->out_snd_device != SND_DEVICE_NONE)) {
2436 /* Disable sidetone only if voice/voip call already exists */
2437 if (voice_is_call_state_active(adev) ||
2438 voice_extn_compress_voip_is_started(adev))
Bhalchandra Gajare45fee282015-06-09 22:23:45 -07002439 voice_set_sidetone(adev, usecase->out_snd_device, false);
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002440
2441 /* Disable aanc only if voice call exists */
2442 if (voice_is_call_state_active(adev))
2443 voice_check_and_update_aanc_path(adev, usecase->out_snd_device, false);
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002444 }
2445
Aalique Grahame22e49102018-12-18 14:23:57 -08002446 if ((out_snd_device == SND_DEVICE_OUT_SPEAKER_AND_BT_A2DP ||
2447 out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02002448 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302449 ALOGW("%s: A2DP profile is not ready, routing to speaker only", __func__);
Aalique Grahame22e49102018-12-18 14:23:57 -08002450 if (out_snd_device == SND_DEVICE_OUT_SPEAKER_SAFE_AND_BT_A2DP)
2451 out_snd_device = SND_DEVICE_OUT_SPEAKER_SAFE;
2452 else
2453 out_snd_device = SND_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05302454 }
2455
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002456 /* Disable current sound devices */
2457 if (usecase->out_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002458 disable_audio_route(adev, usecase);
2459 disable_snd_device(adev, usecase->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002460 }
2461
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002462 if (usecase->in_snd_device != SND_DEVICE_NONE) {
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002463 disable_audio_route(adev, usecase);
2464 disable_snd_device(adev, usecase->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002465 }
2466
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002467 /* Applicable only on the targets that has external modem.
2468 * New device information should be sent to modem before enabling
2469 * the devices to reduce in-call device switch time.
2470 */
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002471 if ((usecase->type == VOICE_CALL) &&
2472 (usecase->in_snd_device != SND_DEVICE_NONE) &&
2473 (usecase->out_snd_device != SND_DEVICE_NONE)) {
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002474 status = platform_switch_voice_call_enable_device_config(adev->platform,
2475 out_snd_device,
2476 in_snd_device);
Vidyakumar Athota21b3bb92014-04-25 11:08:08 -07002477 }
Vidyakumar Athota545dbd32013-11-13 17:30:53 -08002478
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002479 /* Enable new sound devices */
2480 if (out_snd_device != SND_DEVICE_NONE) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08002481 check_usecases_codec_backend(adev, usecase, out_snd_device);
Preetam Singh Ranawat43eac682017-03-07 18:19:02 +05302482 if (platform_check_codec_asrc_support(adev->platform))
2483 check_and_set_asrc_mode(adev, usecase, out_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002484 enable_snd_device(adev, out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002485 }
2486
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002487 if (in_snd_device != SND_DEVICE_NONE) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05302488 check_usecases_capture_codec_backend(adev, usecase, in_snd_device);
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002489 enable_snd_device(adev, in_snd_device);
Ravi Kumar Alamandac4ba7432013-06-05 14:11:39 -07002490 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002491
Avinash Vaish71a8b972014-07-24 15:36:33 +05302492 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Eric Laurentb23d5282013-05-14 15:27:20 -07002493 status = platform_switch_voice_call_device_post(adev->platform,
2494 out_snd_device,
2495 in_snd_device);
Avinash Vaish71a8b972014-07-24 15:36:33 +05302496 enable_audio_route_for_voice_usecases(adev, usecase);
2497 }
Ravi Kumar Alamanda610e8cc2013-02-12 01:42:38 -08002498
sangwoo170731f2013-06-08 15:36:36 +09002499 usecase->in_snd_device = in_snd_device;
2500 usecase->out_snd_device = out_snd_device;
2501
Dhananjay Kumard6d32152016-10-13 16:11:03 +05302502 audio_extn_utils_update_stream_app_type_cfg_for_usecase(adev,
2503 usecase);
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302504 if (usecase->type == PCM_PLAYBACK) {
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002505 if ((24 == usecase->stream.out->bit_width) &&
2506 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_SPEAKER)) {
2507 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2508 } else if ((out_snd_device == SND_DEVICE_OUT_HDMI ||
2509 out_snd_device == SND_DEVICE_OUT_USB_HEADSET ||
2510 out_snd_device == SND_DEVICE_OUT_DISPLAY_PORT) &&
2511 (usecase->stream.out->sample_rate >= OUTPUT_SAMPLING_RATE_44100)) {
2512 /*
2513 * To best utlize DSP, check if the stream sample rate is supported/multiple of
2514 * configured device sample rate, if not update the COPP rate to be equal to the
2515 * device sample rate, else open COPP at stream sample rate
2516 */
2517 platform_check_and_update_copp_sample_rate(adev->platform, out_snd_device,
2518 usecase->stream.out->sample_rate,
2519 &usecase->stream.out->app_type_cfg.sample_rate);
Ashish Jain4826f6c2017-02-06 13:33:20 +05302520 } else if (((out_snd_device != SND_DEVICE_OUT_HEADPHONES_44_1 &&
2521 !audio_is_true_native_stream_active(adev)) &&
Weiyin Jiang6f4c8062016-11-23 15:30:29 +08002522 usecase->stream.out->sample_rate == OUTPUT_SAMPLING_RATE_44100) ||
2523 (usecase->stream.out->sample_rate < OUTPUT_SAMPLING_RATE_44100)) {
2524 usecase->stream.out->app_type_cfg.sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
2525 }
2526
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08002527 /* Notify device change info to effect clients registered */
2528 audio_extn_gef_notify_device_config(
2529 usecase->stream.out->devices,
2530 usecase->stream.out->channel_mask,
2531 usecase->stream.out->app_type_cfg.sample_rate,
2532 platform_get_snd_device_acdb_id(usecase->out_snd_device));
Preetam Singh Ranawata4a37d82014-09-25 16:56:38 +05302533 }
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002534 enable_audio_route(adev, usecase);
sangwoo170731f2013-06-08 15:36:36 +09002535
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08002536 audio_extn_qdsp_set_device(usecase);
Aalique Grahame22e49102018-12-18 14:23:57 -08002537
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002538 /* If input stream is already running then effect needs to be
2539 applied on the new input device that's being enabled here. */
Vidyakumar Athotabbfa5f72018-07-05 18:04:48 -07002540 if ((in_snd_device != SND_DEVICE_NONE) && (adev->active_input != NULL) &&
2541 (!adev->active_input->standby))
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002542 check_and_enable_effect(adev);
2543
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002544 if (usecase->type == VOICE_CALL || usecase->type == VOIP_CALL) {
Vidyakumar Athotaea269c62016-10-31 09:05:59 -07002545 /* Enable aanc only if voice call exists */
2546 if (voice_is_call_state_active(adev))
2547 voice_check_and_update_aanc_path(adev, out_snd_device, true);
2548
Vidyakumar Athota493f2892016-08-14 11:56:55 -07002549 /* Enable sidetone only if other voice/voip call already exists */
2550 if (voice_is_call_state_active(adev) ||
2551 voice_extn_compress_voip_is_started(adev))
2552 voice_set_sidetone(adev, out_snd_device, true);
2553 }
2554
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002555 /* Applicable only on the targets that has external modem.
2556 * Enable device command should be sent to modem only after
2557 * enabling voice call mixer controls
2558 */
Vidyakumar Athota339342f2014-07-01 15:30:57 -07002559 if (usecase->type == VOICE_CALL)
Vidyakumar Athota1fd21792013-11-15 14:50:57 -08002560 status = platform_switch_voice_call_usecase_route_post(adev->platform,
2561 out_snd_device,
2562 in_snd_device);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302563
2564 if (is_btsco_device(out_snd_device, in_snd_device) || is_a2dp_device(out_snd_device)) {
2565
2566 if (usecase->type == VOIP_CALL) {
2567 if (adev->active_input != NULL &&
2568 !adev->active_input->standby) {
2569 if (is_bt_soc_on(adev) == false){
2570 ALOGD("BT SCO MIC disconnected while in connection");
2571 if (adev->active_input->pcm != NULL)
2572 pcm_stop(adev->active_input->pcm);
2573 }
2574 }
2575 if ((usecase->stream.out != NULL) && (usecase->stream.out != adev->primary_output)
2576 && usecase->stream.out->started) {
2577 if (is_bt_soc_on(adev) == false) {
2578 ALOGD("BT SCO/A2DP disconnected while in connection");
2579 out_standby_l(&usecase->stream.out->stream.common);
2580 }
2581 }
2582 } else if ((usecase->stream.out != NULL) &&
2583 !(usecase->stream.out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Surendar Karkae1dc8742018-11-19 16:23:14 +05302584 (usecase->type != TRANSCODE_LOOPBACK_TX) &&
2585 (usecase->type != TRANSCODE_LOOPBACK_RX) &&
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302586 usecase->stream.out->started) {
2587 if (is_bt_soc_on(adev) == false) {
2588 ALOGD("BT SCO/A2dp disconnected while in connection");
2589 out_standby_l(&usecase->stream.out->stream.common);
2590 }
2591 }
2592 }
2593
Yung Ti Su70cb8242018-06-22 17:38:47 +08002594 if (usecase->type != PCM_CAPTURE && usecase == voip_usecase) {
Aalique Grahame22e49102018-12-18 14:23:57 -08002595 struct stream_out *voip_out = voip_usecase->stream.out;
2596 audio_extn_utils_send_app_type_gain(adev,
2597 voip_out->app_type_cfg.app_type,
2598 &voip_out->app_type_cfg.gain[0]);
2599 }
2600
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302601 ALOGD("%s: done",__func__);
2602
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002603 return status;
2604}
2605
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002606static int stop_input_stream(struct stream_in *in)
2607{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05302608 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002609 struct audio_usecase *uc_info;
Pallavid7c7a272018-01-16 11:22:55 +05302610
2611 if (in == NULL) {
2612 ALOGE("%s: stream_in ptr is NULL", __func__);
2613 return -EINVAL;
2614 }
2615
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002616 struct audio_device *adev = in->dev;
2617
Eric Laurent994a6932013-07-17 11:51:42 -07002618 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002619 in->usecase, use_case_table[in->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002620 uc_info = get_usecase_from_list(adev, in->usecase);
2621 if (uc_info == NULL) {
2622 ALOGE("%s: Could not find the usecase (%d) in the list",
2623 __func__, in->usecase);
2624 return -EINVAL;
2625 }
2626
Derek Chenea197282019-01-07 17:35:01 -08002627 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
2628 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002629
Vidyakumar Athota2850d532013-11-19 16:02:12 -08002630 /* Close in-call recording streams */
2631 voice_check_and_stop_incall_rec_usecase(adev, in);
2632
Eric Laurent150dbfe2013-02-27 14:31:02 -08002633 /* 1. Disable stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002634 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002635
2636 /* 2. Disable the tx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07002637 disable_snd_device(adev, uc_info->in_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002638
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002639 list_remove(&uc_info->list);
2640 free(uc_info);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002641
Aalique Grahame2e9b2e42016-12-07 12:43:48 -08002642 adev->active_input = get_next_active_input(adev);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302643 enable_gcov();
Eric Laurent994a6932013-07-17 11:51:42 -07002644 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002645 return ret;
2646}
2647
2648int start_input_stream(struct stream_in *in)
2649{
2650 /* 1. Enable output device and stream routing controls */
Eric Laurentc8400632013-02-14 19:04:54 -08002651 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002652 struct audio_usecase *uc_info;
Preetam Singh Ranawata87e9742018-02-13 16:52:53 +05302653
2654 if (in == NULL) {
2655 ALOGE("%s: stream_in ptr is NULL", __func__);
2656 return -EINVAL;
2657 }
2658
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002659 struct audio_device *adev = in->dev;
Garmond Leunge2433c32017-09-28 21:51:22 -07002660 struct pcm_config config = in->config;
Garmond Leung438932f2017-10-04 19:35:18 -07002661 int usecase = platform_update_usecase_from_source(in->source,in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002662
Mingming Yin2664a5b2015-09-03 10:53:11 -07002663 if (get_usecase_from_list(adev, usecase) == NULL)
2664 in->usecase = usecase;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05302665 ALOGD("%s: enter: stream(%p)usecase(%d: %s)",
2666 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002667
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05302668 if (CARD_STATUS_OFFLINE == in->card_status||
2669 CARD_STATUS_OFFLINE == adev->card_status) {
2670 ALOGW("in->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05302671 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05302672 goto error_config;
2673 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05302674
Ashish Jain1b9b30c2017-05-18 20:57:40 +05302675 if (audio_is_bluetooth_sco_device(in->device)) {
2676 if (!adev->bt_sco_on) {
2677 ALOGE("%s: SCO profile is not ready, return error", __func__);
2678 ret = -EIO;
2679 goto error_config;
2680 }
2681 }
2682
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002683 /* Check if source matches incall recording usecase criteria */
2684 ret = voice_check_and_set_incall_rec_usecase(adev, in);
2685 if (ret)
2686 goto error_config;
2687 else
Mingming Yin2664a5b2015-09-03 10:53:11 -07002688 ALOGV("%s: usecase(%d)", __func__, in->usecase);
2689
2690 if (get_usecase_from_list(adev, in->usecase) != NULL) {
2691 ALOGE("%s: use case assigned already in use, stream(%p)usecase(%d: %s)",
2692 __func__, &in->stream, in->usecase, use_case_table[in->usecase]);
Zhou Song4e0704d2016-04-20 13:00:14 +08002693 return -EINVAL;
Mingming Yin2664a5b2015-09-03 10:53:11 -07002694 }
Shiv Maliyappanahallida107642013-10-17 11:16:13 -07002695
Eric Laurentb23d5282013-05-14 15:27:20 -07002696 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002697 if (in->pcm_device_id < 0) {
2698 ALOGE("%s: Could not find PCM device id for the usecase(%d)",
2699 __func__, in->usecase);
Eric Laurentc8400632013-02-14 19:04:54 -08002700 ret = -EINVAL;
2701 goto error_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002702 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002703
2704 adev->active_input = in;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002705 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002706
2707 if (!uc_info) {
2708 ret = -ENOMEM;
2709 goto error_config;
2710 }
2711
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002712 uc_info->id = in->usecase;
2713 uc_info->type = PCM_CAPTURE;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08002714 uc_info->stream.in = in;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002715 uc_info->devices = in->device;
2716 uc_info->in_snd_device = SND_DEVICE_NONE;
2717 uc_info->out_snd_device = SND_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002718
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08002719 list_add_tail(&adev->usecase_list, &uc_info->list);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002720 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302721 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
2722 adev->perf_lock_opts,
2723 adev->perf_lock_opts_size);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002724 select_devices(adev, in->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002725
Derek Chenea197282019-01-07 17:35:01 -08002726 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
2727 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08002728
Haynes Mathew George16081042017-05-31 17:16:49 -07002729 if (audio_extn_cin_attached_usecase(in->usecase)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302730 ret = audio_extn_cin_start_input_stream(in);
2731 if (ret)
2732 goto error_open;
2733 else
2734 goto done_open;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002735 }
2736
Haynes Mathew George16081042017-05-31 17:16:49 -07002737 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002738 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
Haynes Mathew George16081042017-05-31 17:16:49 -07002739 ALOGE("%s: pcm stream not ready", __func__);
2740 goto error_open;
2741 }
2742 ret = pcm_start(in->pcm);
2743 if (ret < 0) {
2744 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
2745 goto error_open;
2746 }
2747 } else {
2748 unsigned int flags = PCM_IN | PCM_MONOTONIC;
2749 unsigned int pcm_open_retry_count = 0;
2750
2751 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY) {
2752 flags |= PCM_MMAP | PCM_NOIRQ;
2753 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
2754 } else if (in->realtime) {
2755 flags |= PCM_MMAP | PCM_NOIRQ;
2756 }
2757
Garmond Leunge2433c32017-09-28 21:51:22 -07002758 if (audio_extn_ffv_get_stream() == in) {
2759 ALOGD("%s: ffv stream, update pcm config", __func__);
2760 audio_extn_ffv_update_pcm_config(&config);
2761 }
Haynes Mathew George16081042017-05-31 17:16:49 -07002762 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
2763 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
2764
2765 while (1) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002766 ATRACE_BEGIN("pcm_in_open");
Haynes Mathew George16081042017-05-31 17:16:49 -07002767 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
Garmond Leung438932f2017-10-04 19:35:18 -07002768 flags, &config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002769 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05302770 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05302771 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
2772 adev->card_status = CARD_STATUS_OFFLINE;
2773 in->card_status = CARD_STATUS_OFFLINE;
2774 ret = -EIO;
2775 goto error_open;
2776 }
2777
Haynes Mathew George16081042017-05-31 17:16:49 -07002778 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
2779 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
2780 if (in->pcm != NULL) {
2781 pcm_close(in->pcm);
2782 in->pcm = NULL;
2783 }
2784 if (pcm_open_retry_count-- == 0) {
2785 ret = -EIO;
2786 goto error_open;
2787 }
2788 usleep(PROXY_OPEN_WAIT_TIME * 1000);
2789 continue;
2790 }
2791 break;
2792 }
2793
2794 ALOGV("%s: pcm_prepare", __func__);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002795 ATRACE_BEGIN("pcm_in_prepare");
Haynes Mathew George16081042017-05-31 17:16:49 -07002796 ret = pcm_prepare(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002797 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002798 if (ret < 0) {
2799 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
2800 pcm_close(in->pcm);
2801 in->pcm = NULL;
2802 goto error_open;
2803 }
2804 register_in_stream(in);
2805 if (in->realtime) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07002806 ATRACE_BEGIN("pcm_in_start");
Haynes Mathew George16081042017-05-31 17:16:49 -07002807 ret = pcm_start(in->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07002808 ATRACE_END();
Haynes Mathew George16081042017-05-31 17:16:49 -07002809 if (ret < 0) {
2810 ALOGE("%s: RT pcm_start failed ret %d", __func__, ret);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002811 pcm_close(in->pcm);
2812 in->pcm = NULL;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002813 goto error_open;
2814 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07002815 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07002816 }
2817
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002818 check_and_enable_effect(adev);
justinweng20fb6d82019-02-21 18:49:00 -07002819 audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
2820 audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07002821
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05302822done_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08002823 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302824 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07002825 ALOGD("%s: exit", __func__);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302826 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002827 return ret;
2828
2829error_open:
Wei Wangf7ca6c92017-11-21 14:51:20 -08002830 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05302831 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002832 stop_input_stream(in);
Wei Wangf7ca6c92017-11-21 14:51:20 -08002833
Eric Laurentc8400632013-02-14 19:04:54 -08002834error_config:
Dhananjay Kumard4833242016-10-06 22:09:12 +05302835 adev->active_input = get_next_active_input(adev);
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05302836 /*
2837 * sleep 50ms to allow sufficient time for kernel
2838 * drivers to recover incases like SSR.
2839 */
2840 usleep(50000);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07002841 ALOGD("%s: exit: status(%d)", __func__, ret);
Vatsal Buchac09ae062018-11-14 13:25:08 +05302842 enable_gcov();
Eric Laurentc8400632013-02-14 19:04:54 -08002843 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08002844}
2845
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07002846void lock_input_stream(struct stream_in *in)
2847{
2848 pthread_mutex_lock(&in->pre_lock);
2849 pthread_mutex_lock(&in->lock);
2850 pthread_mutex_unlock(&in->pre_lock);
2851}
2852
2853void lock_output_stream(struct stream_out *out)
2854{
2855 pthread_mutex_lock(&out->pre_lock);
2856 pthread_mutex_lock(&out->lock);
2857 pthread_mutex_unlock(&out->pre_lock);
2858}
2859
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002860/* must be called with out->lock locked */
2861static int send_offload_cmd_l(struct stream_out* out, int command)
2862{
2863 struct offload_cmd *cmd = (struct offload_cmd *)calloc(1, sizeof(struct offload_cmd));
2864
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07002865 if (!cmd) {
2866 ALOGE("failed to allocate mem for command 0x%x", command);
2867 return -ENOMEM;
2868 }
2869
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002870 ALOGVV("%s %d", __func__, command);
2871
2872 cmd->cmd = command;
2873 list_add_tail(&out->offload_cmd_list, &cmd->node);
2874 pthread_cond_signal(&out->offload_cond);
2875 return 0;
2876}
2877
2878/* must be called iwth out->lock locked */
2879static void stop_compressed_output_l(struct stream_out *out)
2880{
2881 out->offload_state = OFFLOAD_STATE_IDLE;
2882 out->playback_started = 0;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07002883 out->send_new_metadata = 1;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002884 if (out->compr != NULL) {
2885 compress_stop(out->compr);
2886 while (out->offload_thread_blocked) {
2887 pthread_cond_wait(&out->cond, &out->lock);
2888 }
2889 }
2890}
2891
Varun Balaraje49253e2017-07-06 19:48:56 +05302892bool is_interactive_usecase(audio_usecase_t uc_id)
2893{
2894 unsigned int i;
2895 for (i = 0; i < sizeof(interactive_usecases)/sizeof(interactive_usecases[0]); i++) {
2896 if (uc_id == interactive_usecases[i])
2897 return true;
2898 }
2899 return false;
2900}
2901
2902static audio_usecase_t get_interactive_usecase(struct audio_device *adev)
2903{
2904 audio_usecase_t ret_uc = USECASE_INVALID;
2905 unsigned int intract_uc_index;
2906 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2907
2908 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
2909 for (intract_uc_index = 0; intract_uc_index < num_usecase; intract_uc_index++) {
2910 if (!(adev->interactive_usecase_state & (0x1 << intract_uc_index))) {
2911 adev->interactive_usecase_state |= 0x1 << intract_uc_index;
2912 ret_uc = interactive_usecases[intract_uc_index];
2913 break;
2914 }
2915 }
2916
2917 ALOGV("%s: Interactive usecase is %d", __func__, ret_uc);
2918 return ret_uc;
2919}
2920
2921static void free_interactive_usecase(struct audio_device *adev,
2922 audio_usecase_t uc_id)
2923{
2924 unsigned int interact_uc_index;
2925 unsigned int num_usecase = sizeof(interactive_usecases)/sizeof(interactive_usecases[0]);
2926
2927 for (interact_uc_index = 0; interact_uc_index < num_usecase; interact_uc_index++) {
2928 if (interactive_usecases[interact_uc_index] == uc_id) {
2929 adev->interactive_usecase_state &= ~(0x1 << interact_uc_index);
2930 break;
2931 }
2932 }
2933 ALOGV("%s: free Interactive usecase %d", __func__, uc_id);
2934}
2935
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002936bool is_offload_usecase(audio_usecase_t uc_id)
2937{
2938 unsigned int i;
2939 for (i = 0; i < sizeof(offload_usecases)/sizeof(offload_usecases[0]); i++) {
2940 if (uc_id == offload_usecases[i])
2941 return true;
2942 }
2943 return false;
2944}
2945
Dhananjay Kumarac341582017-02-23 23:42:25 +05302946static audio_usecase_t get_offload_usecase(struct audio_device *adev, bool is_compress)
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002947{
vivek mehta446c3962015-09-14 10:57:35 -07002948 audio_usecase_t ret_uc = USECASE_INVALID;
2949 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002950 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002951 if (!adev->multi_offload_enable) {
Dhananjay Kumarac341582017-02-23 23:42:25 +05302952 if (!is_compress)
vivek mehta446c3962015-09-14 10:57:35 -07002953 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD2;
2954 else
2955 ret_uc = USECASE_AUDIO_PLAYBACK_OFFLOAD;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002956
vivek mehta446c3962015-09-14 10:57:35 -07002957 pthread_mutex_lock(&adev->lock);
2958 if (get_usecase_from_list(adev, ret_uc) != NULL)
2959 ret_uc = USECASE_INVALID;
2960 pthread_mutex_unlock(&adev->lock);
2961
2962 return ret_uc;
2963 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002964
2965 ALOGV("%s: num_usecase: %d", __func__, num_usecase);
vivek mehta446c3962015-09-14 10:57:35 -07002966 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2967 if (!(adev->offload_usecases_state & (0x1 << offload_uc_index))) {
2968 adev->offload_usecases_state |= 0x1 << offload_uc_index;
2969 ret_uc = offload_usecases[offload_uc_index];
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002970 break;
2971 }
2972 }
vivek mehta446c3962015-09-14 10:57:35 -07002973
2974 ALOGV("%s: offload usecase is %d", __func__, ret_uc);
2975 return ret_uc;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002976}
2977
2978static void free_offload_usecase(struct audio_device *adev,
2979 audio_usecase_t uc_id)
2980{
vivek mehta446c3962015-09-14 10:57:35 -07002981 unsigned int offload_uc_index;
Alexy Josephb1379942016-01-29 15:49:38 -08002982 unsigned int num_usecase = sizeof(offload_usecases)/sizeof(offload_usecases[0]);
vivek mehta446c3962015-09-14 10:57:35 -07002983
2984 if (!adev->multi_offload_enable)
2985 return;
2986
2987 for (offload_uc_index = 0; offload_uc_index < num_usecase; offload_uc_index++) {
2988 if (offload_usecases[offload_uc_index] == uc_id) {
2989 adev->offload_usecases_state &= ~(0x1 << offload_uc_index);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07002990 break;
2991 }
2992 }
2993 ALOGV("%s: free offload usecase %d", __func__, uc_id);
2994}
2995
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07002996static void *offload_thread_loop(void *context)
2997{
2998 struct stream_out *out = (struct stream_out *) context;
2999 struct listnode *item;
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003000 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003001
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003002 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_AUDIO);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08003003 //set_sched_policy(0, SP_FOREGROUND);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003004 prctl(PR_SET_NAME, (unsigned long)"Offload Callback", 0, 0, 0);
3005
3006 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003007 lock_output_stream(out);
juyuchen391b5fa2018-12-12 17:58:09 +08003008 out->offload_state = OFFLOAD_STATE_IDLE;
3009 out->playback_started = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003010 for (;;) {
3011 struct offload_cmd *cmd = NULL;
3012 stream_callback_event_t event;
3013 bool send_callback = false;
3014
3015 ALOGVV("%s offload_cmd_list %d out->offload_state %d",
3016 __func__, list_empty(&out->offload_cmd_list),
3017 out->offload_state);
3018 if (list_empty(&out->offload_cmd_list)) {
3019 ALOGV("%s SLEEPING", __func__);
3020 pthread_cond_wait(&out->offload_cond, &out->lock);
3021 ALOGV("%s RUNNING", __func__);
3022 continue;
3023 }
3024
3025 item = list_head(&out->offload_cmd_list);
3026 cmd = node_to_item(item, struct offload_cmd, node);
3027 list_remove(item);
3028
3029 ALOGVV("%s STATE %d CMD %d out->compr %p",
3030 __func__, out->offload_state, cmd->cmd, out->compr);
3031
3032 if (cmd->cmd == OFFLOAD_CMD_EXIT) {
3033 free(cmd);
3034 break;
3035 }
3036
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003037 // allow OFFLOAD_CMD_ERROR reporting during standby
3038 // this is needed to handle failures during compress_open
3039 // Note however that on a pause timeout, the stream is closed
3040 // and no offload usecase will be active. Therefore this
3041 // special case is needed for compress_open failures alone
3042 if (cmd->cmd != OFFLOAD_CMD_ERROR &&
3043 out->compr == NULL) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003044 ALOGE("%s: Compress handle is NULL", __func__);
Haynes Mathew Georgea9abb202016-06-02 14:13:20 -07003045 free(cmd);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003046 pthread_cond_signal(&out->cond);
3047 continue;
3048 }
3049 out->offload_thread_blocked = true;
3050 pthread_mutex_unlock(&out->lock);
3051 send_callback = false;
3052 switch(cmd->cmd) {
3053 case OFFLOAD_CMD_WAIT_FOR_BUFFER:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003054 ALOGD("copl(%p):calling compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003055 compress_wait(out->compr, -1);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003056 ALOGD("copl(%p):out of compress_wait", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003057 send_callback = true;
3058 event = STREAM_CBK_EVENT_WRITE_READY;
3059 break;
3060 case OFFLOAD_CMD_PARTIAL_DRAIN:
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003061 ret = compress_next_track(out->compr);
Sidipotu Ashok55820562014-02-10 16:16:38 +05303062 if(ret == 0) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003063 ALOGD("copl(%p):calling compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303064 ret = compress_partial_drain(out->compr);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003065 ALOGD("copl(%p):out of compress_partial_drain", out);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303066 if (ret < 0)
3067 ret = -errno;
Sidipotu Ashok55820562014-02-10 16:16:38 +05303068 }
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303069 else if (ret == -ETIMEDOUT)
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003070 ret = compress_drain(out->compr);
Krishnankutty Kolathappillyd4f1d132014-01-06 18:33:58 -08003071 else
3072 ALOGE("%s: Next track returned error %d",__func__, ret);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003073 if (-ENETRESET != ret && !(-EINTR == ret &&
3074 CARD_STATUS_OFFLINE == out->card_status)) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303075 send_callback = true;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303076 pthread_mutex_lock(&out->lock);
3077 out->send_new_metadata = 1;
3078 out->send_next_track_params = true;
3079 pthread_mutex_unlock(&out->lock);
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05303080 event = STREAM_CBK_EVENT_DRAIN_READY;
3081 ALOGV("copl(%p):send drain callback, ret %d", out, ret);
3082 } else
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303083 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003084 break;
3085 case OFFLOAD_CMD_DRAIN:
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003086 ALOGD("copl(%p):calling compress_drain", out);
Aniket Kumar Lata3570fb12017-11-08 15:53:44 -08003087 ret = compress_drain(out->compr);
3088 ALOGD("copl(%p):out of compress_drain", out);
3089 // EINTR check avoids drain interruption due to SSR
3090 if (-ENETRESET != ret && !(-EINTR == ret &&
3091 CARD_STATUS_OFFLINE == out->card_status)) {
3092 send_callback = true;
3093 event = STREAM_CBK_EVENT_DRAIN_READY;
3094 } else
3095 ALOGI("%s: Block drain ready event during SSR", __func__);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003096 break;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303097 case OFFLOAD_CMD_ERROR:
3098 ALOGD("copl(%p): sending error callback to AF", out);
3099 send_callback = true;
3100 event = STREAM_CBK_EVENT_ERROR;
3101 break;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003102 default:
3103 ALOGE("%s unknown command received: %d", __func__, cmd->cmd);
3104 break;
3105 }
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003106 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003107 out->offload_thread_blocked = false;
3108 pthread_cond_signal(&out->cond);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003109 if (send_callback && out->client_callback) {
3110 ALOGVV("%s: sending client_callback event %d", __func__, event);
3111 out->client_callback(event, NULL, out->client_cookie);
Eric Laurent6e895242013-09-05 16:10:57 -07003112 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003113 free(cmd);
3114 }
3115
3116 pthread_cond_signal(&out->cond);
3117 while (!list_empty(&out->offload_cmd_list)) {
3118 item = list_head(&out->offload_cmd_list);
3119 list_remove(item);
3120 free(node_to_item(item, struct offload_cmd, node));
3121 }
3122 pthread_mutex_unlock(&out->lock);
3123
3124 return NULL;
3125}
3126
3127static int create_offload_callback_thread(struct stream_out *out)
3128{
3129 pthread_cond_init(&out->offload_cond, (const pthread_condattr_t *) NULL);
3130 list_init(&out->offload_cmd_list);
3131 pthread_create(&out->offload_thread, (const pthread_attr_t *) NULL,
3132 offload_thread_loop, out);
3133 return 0;
3134}
3135
3136static int destroy_offload_callback_thread(struct stream_out *out)
3137{
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003138 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003139 stop_compressed_output_l(out);
3140 send_offload_cmd_l(out, OFFLOAD_CMD_EXIT);
3141
3142 pthread_mutex_unlock(&out->lock);
3143 pthread_join(out->offload_thread, (void **) NULL);
3144 pthread_cond_destroy(&out->offload_cond);
3145
3146 return 0;
3147}
3148
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003149static int stop_output_stream(struct stream_out *out)
3150{
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05303151 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003152 struct audio_usecase *uc_info;
3153 struct audio_device *adev = out->dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08003154 bool has_voip_usecase =
3155 get_usecase_from_list(adev, USECASE_AUDIO_PLAYBACK_VOIP) != NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003156
Eric Laurent994a6932013-07-17 11:51:42 -07003157 ALOGV("%s: enter: usecase(%d: %s)", __func__,
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003158 out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003159 uc_info = get_usecase_from_list(adev, out->usecase);
3160 if (uc_info == NULL) {
3161 ALOGE("%s: Could not find the usecase (%d) in the list",
3162 __func__, out->usecase);
3163 return -EINVAL;
3164 }
3165
Derek Chenea197282019-01-07 17:35:01 -08003166 if (audio_extn_ext_hw_plugin_usecase_stop(adev->ext_hw_plugin, uc_info))
3167 ALOGE("%s: failed to stop ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003168
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003169 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303170 !(audio_extn_passthru_is_passthrough_stream(out))) {
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003171 if (adev->visualizer_stop_output != NULL)
3172 adev->visualizer_stop_output(out->handle, out->pcm_device_id);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003173
3174 audio_extn_dts_remove_state_notifier_node(out->usecase);
3175
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003176 if (adev->offload_effects_stop_output != NULL)
3177 adev->offload_effects_stop_output(out->handle, out->pcm_device_id);
vivek mehtad15d2bf2019-05-17 13:35:10 -07003178 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3179 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3180 audio_low_latency_hint_end();
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08003181 }
Eric Laurentc4aef752013-09-12 17:45:53 -07003182
Arun Mirpurief53ce52018-09-11 18:00:09 -07003183 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3184 voice_set_device_mute_flag(adev, false);
3185
Eric Laurent150dbfe2013-02-27 14:31:02 -08003186 /* 1. Get and set stream specific mixer controls */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003187 disable_audio_route(adev, uc_info);
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003188
3189 /* 2. Disable the rx device */
Haynes Mathew George1376ca62014-04-24 11:55:48 -07003190 disable_snd_device(adev, uc_info->out_snd_device);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003191
Aalique Grahame22e49102018-12-18 14:23:57 -08003192 audio_extn_extspk_update(adev->extspk);
3193
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003194 if (is_offload_usecase(out->usecase)) {
3195 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3196 adev->dsp_bit_width_enforce_mode,
3197 false);
3198 }
Garmond Leung5fd0b552018-04-17 11:56:12 -07003199 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3200 ret = audio_extn_usb_check_and_set_svc_int(uc_info,
3201 false);
3202
3203 if (ret != 0)
3204 check_usecases_codec_backend(adev, uc_info, uc_info->out_snd_device);
3205 /* default service interval was successfully updated,
3206 reopen USB backend with new service interval */
3207 ret = 0;
3208 }
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003209
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003210 list_remove(&uc_info->list);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303211 out->started = 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003212 if (is_offload_usecase(out->usecase) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303213 (audio_extn_passthru_is_passthrough_stream(out))) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003214 ALOGV("Disable passthrough , reset mixer to pcm");
3215 /* NO_PASSTHROUGH */
3216 out->compr_config.codec->compr_passthr = 0;
Mingming Yin21854652016-04-13 11:54:02 -07003217 audio_extn_passthru_on_stop(out);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003218 audio_extn_dolby_set_dap_bypass(adev, DAP_STATE_ON);
3219 }
Eric Laurent07eeafd2013-10-06 12:52:49 -07003220
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05303221 /* Must be called after removing the usecase from list */
3222 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303223 audio_extn_keep_alive_start(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303224
Manish Dewangan21a850a2017-08-14 12:03:55 +05303225 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07003226 ret = audio_extn_ip_hdlr_intf_close(out->ip_hdlr_handle, true, out);
3227 if (ret < 0)
3228 ALOGE("%s: audio_extn_ip_hdlr_intf_close failed %d",__func__, ret);
3229 }
3230
juyuchen2d415992018-11-16 14:15:16 +08003231 /* 1) media + voip output routing to handset must route media back to
3232 speaker when voip stops.
3233 2) trigger voip input to reroute when voip output changes to
3234 hearing aid. */
Aalique Grahame22e49102018-12-18 14:23:57 -08003235 if (has_voip_usecase ||
3236 out->devices & AUDIO_DEVICE_OUT_SPEAKER_SAFE) {
3237 struct listnode *node;
3238 struct audio_usecase *usecase;
3239 list_for_each(node, &adev->usecase_list) {
3240 usecase = node_to_item(node, struct audio_usecase, list);
juyuchen2d415992018-11-16 14:15:16 +08003241 if ((usecase->type == PCM_CAPTURE &&
3242 usecase->id != USECASE_AUDIO_RECORD_VOIP)
3243 || usecase == uc_info)
Aalique Grahame22e49102018-12-18 14:23:57 -08003244 continue;
3245
3246 ALOGD("%s: select_devices at usecase(%d: %s) after removing the usecase(%d: %s)",
3247 __func__, usecase->id, use_case_table[usecase->id],
3248 out->usecase, use_case_table[out->usecase]);
3249 select_devices(adev, usecase->id);
3250 }
3251 }
3252
Garmond Leung5fd0b552018-04-17 11:56:12 -07003253 free(uc_info);
Eric Laurent994a6932013-07-17 11:51:42 -07003254 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003255 return ret;
3256}
3257
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003258struct pcm* pcm_open_prepare_helper(unsigned int snd_card, unsigned int pcm_device_id,
3259 unsigned int flags, unsigned int pcm_open_retry_count,
3260 struct pcm_config *config)
3261{
3262 struct pcm* pcm = NULL;
3263
3264 while (1) {
3265 pcm = pcm_open(snd_card, pcm_device_id, flags, config);
3266 if (pcm == NULL || !pcm_is_ready(pcm)) {
3267 ALOGE("%s: %s", __func__, pcm_get_error(pcm));
3268 if (pcm != NULL) {
3269 pcm_close(pcm);
3270 pcm = NULL;
3271 }
3272 if (pcm_open_retry_count-- == 0)
3273 return NULL;
3274
3275 usleep(PROXY_OPEN_WAIT_TIME * 1000);
3276 continue;
3277 }
3278 break;
3279 }
3280
3281 if (pcm_is_ready(pcm)) {
3282 int ret = pcm_prepare(pcm);
3283 if (ret < 0) {
3284 ALOGE("%s: pcm_prepare returned %d", __func__, ret);
3285 pcm_close(pcm);
3286 pcm = NULL;
3287 }
3288 }
3289
3290 return pcm;
3291}
3292
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003293int start_output_stream(struct stream_out *out)
3294{
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003295 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003296 struct audio_usecase *uc_info;
3297 struct audio_device *adev = out->dev;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003298 char mixer_ctl_name[128];
3299 struct mixer_ctl *ctl = NULL;
3300 char* perf_mode[] = {"ULL", "ULL_PP", "LL"};
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303301 bool a2dp_combo = false;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003302 bool is_haptic_usecase = (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) ? true: false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003303
Haynes Mathew George380745d2017-10-04 15:27:45 -07003304 ATRACE_BEGIN("start_output_stream");
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003305 if ((out->usecase < 0) || (out->usecase >= AUDIO_USECASE_MAX)) {
3306 ret = -EINVAL;
3307 goto error_config;
3308 }
3309
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003310 ALOGD("%s: enter: stream(%p)usecase(%d: %s) devices(%#x) is_haptic_usecase(%d)",
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303311 __func__, &out->stream, out->usecase, use_case_table[out->usecase],
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003312 out->devices, is_haptic_usecase);
Naresh Tanniru4c630392014-05-12 01:05:52 +05303313
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303314 if (CARD_STATUS_OFFLINE == out->card_status ||
3315 CARD_STATUS_OFFLINE == adev->card_status) {
3316 ALOGW("out->card_status or adev->card_status offline, try again");
Dhanalakshmi Siddani4d57e992014-07-17 16:37:51 +05303317 ret = -EIO;
Naresh Tanniru4c630392014-05-12 01:05:52 +05303318 goto error_config;
3319 }
Naresh Tanniru4c630392014-05-12 01:05:52 +05303320
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303321 if (out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02003322 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08003323 if (out->devices &
3324 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303325 a2dp_combo = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303326 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303327 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
3328 ALOGE("%s: A2DP profile is not ready, return error", __func__);
3329 ret = -EAGAIN;
3330 goto error_config;
3331 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05303332 }
3333 }
3334 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303335 if (out->devices & AUDIO_DEVICE_OUT_ALL_SCO) {
3336 if (!adev->bt_sco_on) {
3337 if (out->devices & AUDIO_DEVICE_OUT_SPEAKER) {
3338 //combo usecase just by pass a2dp
3339 ALOGW("%s: SCO is not connected, route it to speaker", __func__);
3340 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
3341 } else {
3342 ALOGE("%s: SCO profile is not ready, return error", __func__);
3343 ret = -EAGAIN;
3344 goto error_config;
3345 }
3346 }
3347 }
3348
Eric Laurentb23d5282013-05-14 15:27:20 -07003349 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003350 if (out->pcm_device_id < 0) {
3351 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
3352 __func__, out->pcm_device_id, out->usecase);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003353 ret = -EINVAL;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003354 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003355 }
3356
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003357 if (is_haptic_usecase) {
3358 adev->haptic_pcm_device_id = platform_get_haptics_pcm_device_id();
3359 if (adev->haptic_pcm_device_id < 0) {
3360 ALOGE("%s: Invalid Haptics pcm device id(%d) for the usecase(%d)",
3361 __func__, adev->haptic_pcm_device_id, out->usecase);
3362 ret = -EINVAL;
3363 goto error_config;
3364 }
3365 }
3366
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003367 uc_info = (struct audio_usecase *)calloc(1, sizeof(struct audio_usecase));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07003368
3369 if (!uc_info) {
3370 ret = -ENOMEM;
3371 goto error_config;
3372 }
3373
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003374 uc_info->id = out->usecase;
3375 uc_info->type = PCM_PLAYBACK;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08003376 uc_info->stream.out = out;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003377 uc_info->devices = out->devices;
3378 uc_info->in_snd_device = SND_DEVICE_NONE;
3379 uc_info->out_snd_device = SND_DEVICE_NONE;
Garmond Leung5fd0b552018-04-17 11:56:12 -07003380
3381 /* This must be called before adding this usecase to the list */
3382 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
3383 audio_extn_usb_check_and_set_svc_int(uc_info, true);
3384 /* USB backend is not reopened immediately.
3385 This is eventually done as part of select_devices */
3386 }
3387
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08003388 list_add_tail(&adev->usecase_list, &uc_info->list);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003389
Wei Wangf7ca6c92017-11-21 14:51:20 -08003390 audio_streaming_hint_start();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303391 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
3392 adev->perf_lock_opts,
3393 adev->perf_lock_opts_size);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303394
3395 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) {
Md Mansoor Ahmeddb1b4f92018-01-25 18:56:31 +05303396 audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_HDMI);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303397 if (audio_extn_passthru_is_enabled() &&
3398 audio_extn_passthru_is_passthrough_stream(out)) {
3399 audio_extn_passthru_on_start(out);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05303400 }
3401 }
3402
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303403 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02003404 (!audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303405 if (!a2dp_combo) {
3406 check_a2dp_restore_l(adev, out, false);
3407 } else {
3408 audio_devices_t dev = out->devices;
Aalique Grahame22e49102018-12-18 14:23:57 -08003409 if (dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
3410 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
3411 else
3412 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05303413 select_devices(adev, out->usecase);
3414 out->devices = dev;
3415 }
3416 } else {
3417 select_devices(adev, out->usecase);
3418 }
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07003419
Arun Mirpurief53ce52018-09-11 18:00:09 -07003420 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK)
3421 voice_set_device_mute_flag(adev, true);
3422
Derek Chenea197282019-01-07 17:35:01 -08003423 if (audio_extn_ext_hw_plugin_usecase_start(adev->ext_hw_plugin, uc_info))
3424 ALOGE("%s: failed to start ext hw plugin", __func__);
Derek Chend2530072014-11-24 12:39:14 -08003425
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003426 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d) format(%#x)",
3427 __func__, adev->snd_card, out->pcm_device_id, out->config.format);
Haynes Mathew George16081042017-05-31 17:16:49 -07003428
3429 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07003430 ALOGD("%s: Starting MMAP stream", __func__);
Haynes Mathew George16081042017-05-31 17:16:49 -07003431 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3432 ALOGE("%s: pcm stream not ready", __func__);
3433 goto error_open;
3434 }
3435 ret = pcm_start(out->pcm);
3436 if (ret < 0) {
3437 ALOGE("%s: MMAP pcm_start failed ret %d", __func__, ret);
3438 goto error_open;
3439 }
Arun Mirpuri5d170872019-03-26 13:21:31 -07003440 out_set_mmap_volume(&out->stream, out->volume_l, out->volume_r);
Haynes Mathew George16081042017-05-31 17:16:49 -07003441 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003442 unsigned int flags = PCM_OUT;
3443 unsigned int pcm_open_retry_count = 0;
3444 if (out->usecase == USECASE_AUDIO_PLAYBACK_AFE_PROXY) {
3445 flags |= PCM_MMAP | PCM_NOIRQ;
3446 pcm_open_retry_count = PROXY_OPEN_RETRY_COUNT;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003447 } else if (out->realtime) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08003448 flags |= PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07003449 } else
3450 flags |= PCM_MONOTONIC;
3451
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08003452 if ((adev->vr_audio_mode_enabled) &&
3453 (out->flags & AUDIO_OUTPUT_FLAG_RAW)) {
3454 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
3455 "PCM_Dev %d Topology", out->pcm_device_id);
3456 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
3457 if (!ctl) {
3458 ALOGI("%s: Could not get ctl for mixer cmd might be ULL - %s",
3459 __func__, mixer_ctl_name);
3460 } else {
3461 //if success use ULLPP
3462 ALOGI("%s: mixer ctrl %s succeeded setting up ULL for %d",
3463 __func__, mixer_ctl_name, out->pcm_device_id);
3464 //There is a still a possibility that some sessions
3465 // that request for FAST|RAW when 3D audio is active
3466 //can go through ULLPP. Ideally we expects apps to
3467 //listen to audio focus and stop concurrent playback
3468 //Also, we will look for mode flag (voice_in_communication)
3469 //before enabling the realtime flag.
3470 mixer_ctl_set_enum_by_string(ctl, perf_mode[1]);
3471 }
3472 }
3473
Surendar Karka91fa3682018-07-02 18:12:12 +05303474 if (out->realtime)
3475 platform_set_stream_channel_map(adev->platform, out->channel_mask,
3476 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
3477
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003478 out->pcm = pcm_open_prepare_helper(adev->snd_card, out->pcm_device_id,
3479 flags, pcm_open_retry_count,
3480 &(out->config));
3481 if (out->pcm == NULL) {
3482 ret = -EIO;
3483 goto error_open;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003484 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003485
3486 if (is_haptic_usecase) {
3487 adev->haptic_pcm = pcm_open_prepare_helper(adev->snd_card,
3488 adev->haptic_pcm_device_id,
3489 flags, pcm_open_retry_count,
3490 &(adev->haptics_config));
3491 // failure to open haptics pcm shouldnt stop audio,
3492 // so do not close audio pcm in case of error
Vignesh Kulothungane4039c12019-05-07 15:51:39 -07003493
3494 if (property_get_bool("vendor.audio.enable_haptic_audio_sync", false)) {
3495 ALOGD("%s: enable haptic audio synchronization", __func__);
3496 platform_set_qtime(adev->platform, out->pcm_device_id, adev->haptic_pcm_device_id);
3497 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003498 }
3499
Surendar Karka91fa3682018-07-02 18:12:12 +05303500 if (!out->realtime)
3501 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Surendar Karkaf51b5842018-04-26 11:28:38 +05303502 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003503
Zhou Song2b8f28f2017-09-11 10:51:38 +08003504 // apply volume for voip playback after path is set up
3505 if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3506 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Ramu Gottipati36547092018-12-28 11:32:09 +05303507 else if ((out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY || out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
3508 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) && (out->apply_volume)) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05303509 out_set_pcm_volume(&out->stream, out->volume_l, out->volume_r);
3510 out->apply_volume = false;
3511 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003512 } else {
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07003513 platform_set_stream_channel_map(adev->platform, out->channel_mask,
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05303514 out->pcm_device_id, &out->channel_map_param.channel_map[0]);
Xiaojun Sang785b5da2017-08-03 15:52:29 +08003515 audio_enable_asm_bit_width_enforce_mode(adev->mixer,
3516 adev->dsp_bit_width_enforce_mode,
3517 true);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003518 out->pcm = NULL;
Haynes Mathew George380745d2017-10-04 15:27:45 -07003519 ATRACE_BEGIN("compress_open");
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08003520 out->compr = compress_open(adev->snd_card,
3521 out->pcm_device_id,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003522 COMPRESS_IN, &out->compr_config);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003523 ATRACE_END();
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05303524 if (errno == ENETRESET && !is_compress_ready(out->compr)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05303525 ALOGE("%s: compress_open failed errno:%d\n", __func__, errno);
3526 adev->card_status = CARD_STATUS_OFFLINE;
3527 out->card_status = CARD_STATUS_OFFLINE;
3528 ret = -EIO;
3529 goto error_open;
3530 }
3531
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003532 if (out->compr && !is_compress_ready(out->compr)) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003533 ALOGE("%s: failed /w error %s", __func__, compress_get_error(out->compr));
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003534 compress_close(out->compr);
3535 out->compr = NULL;
3536 ret = -EIO;
3537 goto error_open;
3538 }
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303539 /* compress_open sends params of the track, so reset the flag here */
3540 out->is_compr_metadata_avail = false;
3541
Ben Rombergerd771a7c2017-02-22 18:05:17 -08003542 if (out->client_callback)
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003543 compress_nonblock(out->compr, out->non_blocking);
Eric Laurentc4aef752013-09-12 17:45:53 -07003544
Fred Oh3f43e742015-03-04 18:42:34 -08003545 /* Since small bufs uses blocking writes, a write will be blocked
3546 for the default max poll time (20s) in the event of an SSR.
3547 Reduce the poll time to observe and deal with SSR faster.
3548 */
Ashish Jain5106d362016-05-11 19:23:33 +05303549 if (!out->non_blocking) {
Fred Oh3f43e742015-03-04 18:42:34 -08003550 compress_set_max_poll_wait(out->compr, 1000);
3551 }
3552
Manish Dewangan69426c82017-01-30 17:35:36 +05303553 audio_extn_utils_compress_set_render_mode(out);
Manish Dewangan58229382017-02-02 15:48:41 +05303554 audio_extn_utils_compress_set_clk_rec_mode(uc_info);
Manish Dewangan69426c82017-01-30 17:35:36 +05303555
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003556 audio_extn_dts_create_state_notifier_node(out->usecase);
3557 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
3558 popcount(out->channel_mask),
3559 out->playback_started);
3560
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003561#ifdef DS1_DOLBY_DDP_ENABLED
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05303562 if (audio_extn_utils_is_dolby_format(out->format))
Subhash Chandra Bose Naripeddy7690c562013-12-14 00:34:53 -08003563 audio_extn_dolby_send_ddp_endp_params(adev);
3564#endif
Preetam Singh Ranawatd18d8832017-02-08 17:34:54 +05303565 if (!(audio_extn_passthru_is_passthrough_stream(out)) &&
3566 (out->sample_rate != 176400 && out->sample_rate <= 192000)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003567 if (adev->visualizer_start_output != NULL)
3568 adev->visualizer_start_output(out->handle, out->pcm_device_id);
3569 if (adev->offload_effects_start_output != NULL)
Ashish Jain5106d362016-05-11 19:23:33 +05303570 adev->offload_effects_start_output(out->handle, out->pcm_device_id, adev->mixer);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08003571 audio_extn_check_and_set_dts_hpx_state(adev);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07003572 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003573 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003574
3575 if (ret == 0) {
3576 register_out_stream(out);
3577 if (out->realtime) {
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07003578 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
3579 ALOGE("%s: pcm stream not ready", __func__);
3580 goto error_open;
3581 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07003582 ATRACE_BEGIN("pcm_start");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003583 ret = pcm_start(out->pcm);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003584 ATRACE_END();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003585 if (ret < 0)
3586 goto error_open;
3587 }
3588 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003589 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303590 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamandac7d9bef2015-09-30 22:27:26 -07003591 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003592
vivek mehtad15d2bf2019-05-17 13:35:10 -07003593 if (out->usecase == USECASE_AUDIO_PLAYBACK_ULL ||
3594 out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3595 audio_low_latency_hint_start();
3596 }
3597
Manish Dewangan21a850a2017-08-14 12:03:55 +05303598 if (out->ip_hdlr_handle) {
Vidyakumar Athota6d655882017-05-22 18:26:24 -07003599 ret = audio_extn_ip_hdlr_intf_open(out->ip_hdlr_handle, true, out, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07003600 if (ret < 0)
3601 ALOGE("%s: audio_extn_ip_hdlr_intf_open failed %d",__func__, ret);
3602 }
3603
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07003604 // consider a scenario where on pause lower layers are tear down.
3605 // so on resume, swap mixer control need to be sent only when
3606 // backend is active, hence rather than sending from enable device
3607 // sending it from start of streamtream
3608
3609 platform_set_swap_channels(adev, true);
3610
Haynes Mathew George380745d2017-10-04 15:27:45 -07003611 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303612 enable_gcov();
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003613 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003614error_open:
Vignesh Kulothungana6927272019-02-20 15:17:07 -08003615 if (adev->haptic_pcm) {
3616 pcm_close(adev->haptic_pcm);
3617 adev->haptic_pcm = NULL;
3618 }
Wei Wangf7ca6c92017-11-21 14:51:20 -08003619 audio_streaming_hint_end();
Sudheer Papothifa9d2282015-09-17 01:53:25 +05303620 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003621 stop_output_stream(out);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003622error_config:
Laxminath Kasam2cb4b752015-09-24 03:59:15 +05303623 /*
3624 * sleep 50ms to allow sufficient time for kernel
3625 * drivers to recover incases like SSR.
3626 */
3627 usleep(50000);
Haynes Mathew George380745d2017-10-04 15:27:45 -07003628 ATRACE_END();
Vatsal Buchac09ae062018-11-14 13:25:08 +05303629 enable_gcov();
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08003630 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003631}
3632
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003633static int check_input_parameters(uint32_t sample_rate,
3634 audio_format_t format,
Aalique Grahame22e49102018-12-18 14:23:57 -08003635 int channel_count,
3636 bool is_usb_hifi)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003637{
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003638 int ret = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003639
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303640 if (((format != AUDIO_FORMAT_PCM_16_BIT) && (format != AUDIO_FORMAT_PCM_8_24_BIT) &&
3641 (format != AUDIO_FORMAT_PCM_24_BIT_PACKED) && (format != AUDIO_FORMAT_PCM_32_BIT) &&
3642 (format != AUDIO_FORMAT_PCM_FLOAT)) &&
Mingming Yine62d7842013-10-25 16:26:03 -07003643 !voice_extn_compress_voip_is_format_supported(format) &&
Ralf Herzaec80262018-07-03 07:08:49 +02003644 !audio_extn_compr_cap_format_supported(format) &&
3645 !audio_extn_cin_format_supported(format))
Haynes Mathew George484e8d22017-07-31 18:55:17 -07003646 ret = -EINVAL;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003647
Aalique Grahame22e49102018-12-18 14:23:57 -08003648 int max_channel_count = is_usb_hifi ? MAX_HIFI_CHANNEL_COUNT : MAX_CHANNEL_COUNT;
3649 if ((channel_count < MIN_CHANNEL_COUNT) || (channel_count > max_channel_count)) {
3650 ALOGE("%s: unsupported channel count (%d) passed Min / Max (%d / %d)", __func__,
3651 channel_count, MIN_CHANNEL_COUNT, max_channel_count);
3652 return -EINVAL;
3653 }
3654
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003655 switch (channel_count) {
3656 case 1:
3657 case 2:
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05303658 case 3:
3659 case 4:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003660 case 6:
Karthikeyan Mani07faa602018-08-20 11:01:32 -07003661 case 8:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003662 break;
3663 default:
3664 ret = -EINVAL;
3665 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003666
3667 switch (sample_rate) {
3668 case 8000:
3669 case 11025:
3670 case 12000:
3671 case 16000:
3672 case 22050:
3673 case 24000:
3674 case 32000:
3675 case 44100:
3676 case 48000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003677 case 88200:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303678 case 96000:
Haynes Mathew Georgec9253d12017-12-13 15:58:28 -08003679 case 176400:
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303680 case 192000:
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003681 break;
3682 default:
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003683 ret = -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003684 }
3685
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08003686 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003687}
3688
Naresh Tanniru04f71882018-06-26 17:46:22 +05303689
3690/** Add a value in a list if not already present.
3691 * @return true if value was successfully inserted or already present,
3692 * false if the list is full and does not contain the value.
3693 */
3694static bool register_uint(uint32_t value, uint32_t* list, size_t list_length) {
3695 for (size_t i = 0; i < list_length; i++) {
3696 if (list[i] == value) return true; // value is already present
3697 if (list[i] == 0) { // no values in this slot
3698 list[i] = value;
3699 return true; // value inserted
3700 }
3701 }
3702 return false; // could not insert value
3703}
3704
3705/** Add channel_mask in supported_channel_masks if not already present.
3706 * @return true if channel_mask was successfully inserted or already present,
3707 * false if supported_channel_masks is full and does not contain channel_mask.
3708 */
3709static void register_channel_mask(audio_channel_mask_t channel_mask,
3710 audio_channel_mask_t supported_channel_masks[static MAX_SUPPORTED_CHANNEL_MASKS]) {
3711 ALOGE_IF(!register_uint(channel_mask, supported_channel_masks, MAX_SUPPORTED_CHANNEL_MASKS),
3712 "%s: stream can not declare supporting its channel_mask %x", __func__, channel_mask);
3713}
3714
3715/** Add format in supported_formats if not already present.
3716 * @return true if format was successfully inserted or already present,
3717 * false if supported_formats is full and does not contain format.
3718 */
3719static void register_format(audio_format_t format,
3720 audio_format_t supported_formats[static MAX_SUPPORTED_FORMATS]) {
3721 ALOGE_IF(!register_uint(format, supported_formats, MAX_SUPPORTED_FORMATS),
3722 "%s: stream can not declare supporting its format %x", __func__, format);
3723}
3724/** Add sample_rate in supported_sample_rates if not already present.
3725 * @return true if sample_rate was successfully inserted or already present,
3726 * false if supported_sample_rates is full and does not contain sample_rate.
3727 */
3728static void register_sample_rate(uint32_t sample_rate,
3729 uint32_t supported_sample_rates[static MAX_SUPPORTED_SAMPLE_RATES]) {
3730 ALOGE_IF(!register_uint(sample_rate, supported_sample_rates, MAX_SUPPORTED_SAMPLE_RATES),
3731 "%s: stream can not declare supporting its sample rate %x", __func__, sample_rate);
3732}
3733
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003734static inline uint32_t lcm(uint32_t num1, uint32_t num2)
3735{
3736 uint32_t high = num1, low = num2, temp = 0;
3737
3738 if (!num1 || !num2)
3739 return 0;
3740
3741 if (num1 < num2) {
3742 high = num2;
3743 low = num1;
3744 }
3745
3746 while (low != 0) {
3747 temp = low;
3748 low = high % low;
3749 high = temp;
3750 }
3751 return (num1 * num2)/high;
3752}
3753
3754static inline uint32_t nearest_multiple(uint32_t num, uint32_t multiplier)
3755{
3756 uint32_t remainder = 0;
3757
3758 if (!multiplier)
3759 return num;
3760
3761 remainder = num % multiplier;
3762 if (remainder)
3763 num += (multiplier - remainder);
3764
3765 return num;
3766}
3767
Aalique Grahame22e49102018-12-18 14:23:57 -08003768static size_t get_stream_buffer_size(size_t duration_ms,
3769 uint32_t sample_rate,
3770 audio_format_t format,
3771 int channel_count,
3772 bool is_low_latency)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003773{
3774 size_t size = 0;
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003775 uint32_t bytes_per_period_sample = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003776
Aalique Grahame22e49102018-12-18 14:23:57 -08003777 size = (sample_rate * duration_ms) / 1000;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003778 if (is_low_latency)
3779 size = configured_low_latency_capture_period_size;
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05303780
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003781 bytes_per_period_sample = audio_bytes_per_sample(format) * channel_count;
Aalique Grahame22e49102018-12-18 14:23:57 -08003782 size *= audio_bytes_per_sample(format) * channel_count;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003783
Ralf Herzbd08d632018-09-28 15:50:49 +02003784 /* make sure the size is multiple of 32 bytes and additionally multiple of
3785 * the frame_size (required for 24bit samples and non-power-of-2 channel counts)
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003786 * At 48 kHz mono 16-bit PCM:
3787 * 5.000 ms = 240 frames = 15*16*1*2 = 480, a whole multiple of 32 (15)
3788 * 3.333 ms = 160 frames = 10*16*1*2 = 320, a whole multiple of 32 (10)
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003789 * Also, make sure the size is multiple of bytes per period sample
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07003790 */
Karthikeyan Manib38769c2018-11-07 15:44:13 -08003791 size = nearest_multiple(size, lcm(32, bytes_per_period_sample));
Ravi Kumar Alamanda33d33062013-06-11 14:40:01 -07003792
3793 return size;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003794}
3795
Aalique Grahame22e49102018-12-18 14:23:57 -08003796static size_t get_input_buffer_size(uint32_t sample_rate,
3797 audio_format_t format,
3798 int channel_count,
3799 bool is_low_latency)
3800{
3801 /* Don't know if USB HIFI in this context so use true to be conservative */
3802 if (check_input_parameters(sample_rate, format, channel_count,
3803 true /*is_usb_hifi */) != 0)
3804 return 0;
3805
3806 return get_stream_buffer_size(AUDIO_CAPTURE_PERIOD_DURATION_MSEC,
3807 sample_rate,
3808 format,
3809 channel_count,
3810 is_low_latency);
3811}
3812
Derek Chenf6318be2017-06-12 17:16:24 -04003813size_t get_output_period_size(uint32_t sample_rate,
3814 audio_format_t format,
3815 int channel_count,
3816 int duration /*in millisecs*/)
Ashish Jain058165c2016-09-28 23:18:48 +05303817{
3818 size_t size = 0;
3819 uint32_t bytes_per_sample = audio_bytes_per_sample(format);
3820
3821 if ((duration == 0) || (sample_rate == 0) ||
3822 (bytes_per_sample == 0) || (channel_count == 0)) {
3823 ALOGW("Invalid config duration %d sr %d bps %d ch %d", duration, sample_rate,
3824 bytes_per_sample, channel_count);
3825 return -EINVAL;
3826 }
3827
3828 size = (sample_rate *
3829 duration *
3830 bytes_per_sample *
3831 channel_count) / 1000;
3832 /*
3833 * To have same PCM samples for all channels, the buffer size requires to
3834 * be multiple of (number of channels * bytes per sample)
3835 * For writes to succeed, the buffer must be written at address which is multiple of 32
3836 */
3837 size = ALIGN(size, (bytes_per_sample * channel_count * 32));
3838
3839 return (size/(channel_count * bytes_per_sample));
3840}
3841
Zhou Song48453a02018-01-10 17:50:59 +08003842static uint64_t get_actual_pcm_frames_rendered(struct stream_out *out, struct timespec *timestamp)
Ashish Jain5106d362016-05-11 19:23:33 +05303843{
3844 uint64_t actual_frames_rendered = 0;
3845 size_t kernel_buffer_size = out->compr_config.fragment_size * out->compr_config.fragments;
3846
3847 /* This adjustment accounts for buffering after app processor.
3848 * It is based on estimated DSP latency per use case, rather than exact.
3849 */
3850 int64_t platform_latency = platform_render_latency(out->usecase) *
3851 out->sample_rate / 1000000LL;
3852
Zhou Song48453a02018-01-10 17:50:59 +08003853 pthread_mutex_lock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303854 /* not querying actual state of buffering in kernel as it would involve an ioctl call
3855 * which then needs protection, this causes delay in TS query for pcm_offload usecase
3856 * hence only estimate.
3857 */
3858 int64_t signed_frames = out->written - kernel_buffer_size;
3859
3860 signed_frames = signed_frames / (audio_bytes_per_sample(out->format) * popcount(out->channel_mask)) - platform_latency;
3861
Zhou Song48453a02018-01-10 17:50:59 +08003862 if (signed_frames > 0) {
Ashish Jain5106d362016-05-11 19:23:33 +05303863 actual_frames_rendered = signed_frames;
Zhou Song48453a02018-01-10 17:50:59 +08003864 if (timestamp != NULL )
3865 *timestamp = out->writeAt;
3866 } else if (timestamp != NULL) {
3867 clock_gettime(CLOCK_MONOTONIC, timestamp);
3868 }
3869 pthread_mutex_unlock(&out->position_query_lock);
Ashish Jain5106d362016-05-11 19:23:33 +05303870
3871 ALOGVV("%s signed frames %lld out_written %lld kernel_buffer_size %d"
3872 "bytes/sample %zu channel count %d", __func__,(long long int)signed_frames,
3873 (long long int)out->written, (int)kernel_buffer_size,
3874 audio_bytes_per_sample(out->compr_config.codec->format),
3875 popcount(out->channel_mask));
3876
3877 return actual_frames_rendered;
3878}
3879
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003880static uint32_t out_get_sample_rate(const struct audio_stream *stream)
3881{
3882 struct stream_out *out = (struct stream_out *)stream;
3883
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003884 return out->sample_rate;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003885}
3886
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003887static int out_set_sample_rate(struct audio_stream *stream __unused,
3888 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003889{
3890 return -ENOSYS;
3891}
3892
3893static size_t out_get_buffer_size(const struct audio_stream *stream)
3894{
3895 struct stream_out *out = (struct stream_out *)stream;
3896
Varun Balaraje49253e2017-07-06 19:48:56 +05303897 if (is_interactive_usecase(out->usecase)) {
Sri Karri27279e12017-08-07 16:05:20 +05303898 return out->config.period_size * out->config.period_count;
Varun Balaraje49253e2017-07-06 19:48:56 +05303899 } else if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Naresh Tanniruee3499a2017-01-05 14:05:35 +05303900 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
3901 return out->compr_config.fragment_size - sizeof(struct snd_codec_metadata);
3902 else
3903 return out->compr_config.fragment_size;
3904 } else if(out->usecase == USECASE_COMPRESS_VOIP_CALL)
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08003905 return voice_extn_compress_voip_out_get_buffer_size(out);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07003906 else if(out->usecase == USECASE_AUDIO_PLAYBACK_VOIP)
3907 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 +05303908 else if (is_offload_usecase(out->usecase) &&
3909 out->flags == AUDIO_OUTPUT_FLAG_DIRECT)
Ashish Jain83a6cc22016-06-28 14:34:17 +05303910 return out->hal_fragment_size;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003911
Haynes Mathew George5beddd42016-06-27 18:33:40 -07003912 return out->config.period_size * out->af_period_multiplier *
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07003913 audio_stream_out_frame_size((const struct audio_stream_out *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003914}
3915
3916static uint32_t out_get_channels(const struct audio_stream *stream)
3917{
3918 struct stream_out *out = (struct stream_out *)stream;
3919
3920 return out->channel_mask;
3921}
3922
3923static audio_format_t out_get_format(const struct audio_stream *stream)
3924{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003925 struct stream_out *out = (struct stream_out *)stream;
3926
3927 return out->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003928}
3929
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07003930static int out_set_format(struct audio_stream *stream __unused,
3931 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003932{
3933 return -ENOSYS;
3934}
3935
3936static int out_standby(struct audio_stream *stream)
3937{
3938 struct stream_out *out = (struct stream_out *)stream;
3939 struct audio_device *adev = out->dev;
Haynes Mathew George16081042017-05-31 17:16:49 -07003940 bool do_stop = true;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003941
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05303942 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
3943 stream, out->usecase, use_case_table[out->usecase]);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003944
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07003945 lock_output_stream(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003946 if (!out->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07003947 if (adev->adm_deregister_stream)
3948 adev->adm_deregister_stream(adev->adm_data, out->handle);
3949
Haynes Mathew George7fce0a52016-06-23 18:22:27 -07003950 if (is_offload_usecase(out->usecase))
3951 stop_compressed_output_l(out);
3952
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08003953 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003954 out->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08003955 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
3956 voice_extn_compress_voip_close_output_stream(stream);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05303957 out->started = 0;
Zhou Songa8895042016-07-05 17:54:22 +08003958 pthread_mutex_unlock(&adev->lock);
3959 pthread_mutex_unlock(&out->lock);
3960 ALOGD("VOIP output entered standby");
3961 return 0;
3962 } else if (!is_offload_usecase(out->usecase)) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003963 if (out->pcm) {
3964 pcm_close(out->pcm);
3965 out->pcm = NULL;
3966 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003967 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
3968 do_stop = out->playback_started;
3969 out->playback_started = false;
3970 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003971 } else {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07003972 ALOGD("copl(%p):standby", out);
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05303973 out->send_next_track_params = false;
3974 out->is_compr_metadata_avail = false;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07003975 out->gapless_mdata.encoder_delay = 0;
3976 out->gapless_mdata.encoder_padding = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07003977 if (out->compr != NULL) {
3978 compress_close(out->compr);
3979 out->compr = NULL;
3980 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003981 }
Haynes Mathew George16081042017-05-31 17:16:49 -07003982 if (do_stop) {
3983 stop_output_stream(out);
3984 }
Eric Laurent150dbfe2013-02-27 14:31:02 -08003985 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003986 }
3987 pthread_mutex_unlock(&out->lock);
Ashish Jainbbce4322016-02-16 13:25:27 +05303988 ALOGD("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08003989 return 0;
3990}
3991
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303992static int out_on_error(struct audio_stream *stream)
3993{
3994 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07003995 int status = 0;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05303996
3997 lock_output_stream(out);
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08003998 // always send CMD_ERROR for offload streams, this
3999 // is needed e.g. when SSR happens within compress_open
4000 // since the stream is active, offload_callback_thread is also active.
4001 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
4002 stop_compressed_output_l(out);
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004003 }
4004 pthread_mutex_unlock(&out->lock);
4005
4006 status = out_standby(&out->stream.common);
4007
4008 lock_output_stream(out);
4009 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Haynes Mathew Georgeee5836f2017-11-21 18:02:10 -08004010 send_offload_cmd_l(out, OFFLOAD_CMD_ERROR);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304011 }
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05304012
4013 if (is_offload_usecase(out->usecase) && out->card_status == CARD_STATUS_OFFLINE) {
4014 ALOGD("Setting previous card status if offline");
4015 out->prev_card_status_offline = true;
4016 }
4017
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304018 pthread_mutex_unlock(&out->lock);
4019
Ben Rombergerfd02a2f2018-09-17 10:23:23 -07004020 return status;
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304021}
4022
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304023/*
4024 *standby implementation without locks, assumes that the callee already
4025 *has taken adev and out lock.
4026 */
4027int out_standby_l(struct audio_stream *stream)
4028{
4029 struct stream_out *out = (struct stream_out *)stream;
4030 struct audio_device *adev = out->dev;
4031
4032 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
4033 stream, out->usecase, use_case_table[out->usecase]);
4034
4035 if (!out->standby) {
Haynes Mathew George380745d2017-10-04 15:27:45 -07004036 ATRACE_BEGIN("out_standby_l");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304037 if (adev->adm_deregister_stream)
4038 adev->adm_deregister_stream(adev->adm_data, out->handle);
4039
4040 if (is_offload_usecase(out->usecase))
4041 stop_compressed_output_l(out);
4042
4043 out->standby = true;
4044 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
4045 voice_extn_compress_voip_close_output_stream(stream);
4046 out->started = 0;
4047 ALOGD("VOIP output entered standby");
Haynes Mathew George380745d2017-10-04 15:27:45 -07004048 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304049 return 0;
4050 } else if (!is_offload_usecase(out->usecase)) {
4051 if (out->pcm) {
4052 pcm_close(out->pcm);
4053 out->pcm = NULL;
4054 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004055 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS) {
4056 if (adev->haptic_pcm) {
4057 pcm_close(adev->haptic_pcm);
4058 adev->haptic_pcm = NULL;
4059 }
4060
4061 if (adev->haptic_buffer != NULL) {
4062 free(adev->haptic_buffer);
4063 adev->haptic_buffer = NULL;
4064 adev->haptic_buffer_size = 0;
4065 }
4066 adev->haptic_pcm_device_id = 0;
4067 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304068 } else {
4069 ALOGD("copl(%p):standby", out);
4070 out->send_next_track_params = false;
4071 out->is_compr_metadata_avail = false;
4072 out->gapless_mdata.encoder_delay = 0;
4073 out->gapless_mdata.encoder_padding = 0;
4074 if (out->compr != NULL) {
4075 compress_close(out->compr);
4076 out->compr = NULL;
4077 }
4078 }
4079 stop_output_stream(out);
Haynes Mathew George380745d2017-10-04 15:27:45 -07004080 ATRACE_END();
Ashish Jain1b9b30c2017-05-18 20:57:40 +05304081 }
4082 ALOGD("%s: exit", __func__);
4083 return 0;
4084}
4085
Aalique Grahame22e49102018-12-18 14:23:57 -08004086static int out_dump(const struct audio_stream *stream, int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004087{
Aalique Grahame22e49102018-12-18 14:23:57 -08004088 struct stream_out *out = (struct stream_out *)stream;
4089
4090 // We try to get the lock for consistency,
4091 // but it isn't necessary for these variables.
4092 // If we're not in standby, we may be blocked on a write.
4093 const bool locked = (pthread_mutex_trylock(&out->lock) == 0);
4094 dprintf(fd, " Standby: %s\n", out->standby ? "yes" : "no");
4095 dprintf(fd, " Frames written: %lld\n", (long long)out->written);
4096
4097 if (locked) {
4098 pthread_mutex_unlock(&out->lock);
4099 }
4100
4101 // dump error info
4102 (void)error_log_dump(
4103 out->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
4104
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004105 return 0;
4106}
4107
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004108static int parse_compress_metadata(struct stream_out *out, struct str_parms *parms)
4109{
4110 int ret = 0;
4111 char value[32];
ApurupaPattapu2e084df2013-12-18 15:47:59 -08004112
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004113 if (!out || !parms) {
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004114 ALOGE("%s: return invalid ",__func__);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004115 return -EINVAL;
4116 }
4117
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304118 ret = audio_extn_parse_compress_metadata(out, parms);
Weiyin Jiang18ac4e92015-03-15 15:03:40 +08004119
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004120 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_DELAY_SAMPLES, value, sizeof(value));
4121 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304122 out->gapless_mdata.encoder_delay = atoi(value); //whats a good limit check?
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004123 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004124 ret = str_parms_get_str(parms, AUDIO_OFFLOAD_CODEC_PADDING_SAMPLES, value, sizeof(value));
4125 if (ret >= 0) {
Satya Krishna Pindiproli70471602015-04-24 19:12:43 +05304126 out->gapless_mdata.encoder_padding = atoi(value);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004127 }
4128
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004129 ALOGV("%s new encoder delay %u and padding %u", __func__,
4130 out->gapless_mdata.encoder_delay, out->gapless_mdata.encoder_padding);
4131
4132 return 0;
4133}
4134
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004135static bool output_drives_call(struct audio_device *adev, struct stream_out *out)
4136{
4137 return out == adev->primary_output || out == adev->voice_tx_output;
4138}
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004139
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304140// note: this call is safe only if the stream_cb is
4141// removed first in close_output_stream (as is done now).
4142static void out_snd_mon_cb(void * stream, struct str_parms * parms)
4143{
4144 if (!stream || !parms)
4145 return;
4146
4147 struct stream_out *out = (struct stream_out *)stream;
4148 struct audio_device *adev = out->dev;
4149
4150 card_status_t status;
4151 int card;
4152 if (parse_snd_card_status(parms, &card, &status) < 0)
4153 return;
4154
4155 pthread_mutex_lock(&adev->lock);
4156 bool valid_cb = (card == adev->snd_card);
4157 pthread_mutex_unlock(&adev->lock);
4158
4159 if (!valid_cb)
4160 return;
4161
4162 lock_output_stream(out);
4163 if (out->card_status != status)
4164 out->card_status = status;
4165 pthread_mutex_unlock(&out->lock);
4166
4167 ALOGI("out_snd_mon_cb for card %d usecase %s, status %s", card,
4168 use_case_table[out->usecase],
4169 status == CARD_STATUS_OFFLINE ? "offline" : "online");
4170
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304171 if (status == CARD_STATUS_OFFLINE) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304172 out_on_error(stream);
Aditya Bavanari59ebed42019-02-05 17:44:57 +05304173 if (voice_is_call_state_active(adev) &&
4174 out == adev->primary_output) {
4175 ALOGD("%s: SSR/PDR occurred, end all calls\n", __func__);
4176 pthread_mutex_lock(&adev->lock);
4177 voice_stop_call(adev);
4178 adev->mode = AUDIO_MODE_NORMAL;
4179 pthread_mutex_unlock(&adev->lock);
4180 }
4181 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05304182 return;
4183}
4184
Kevin Rocardfce19002017-08-07 19:21:36 -07004185static int get_alive_usb_card(struct str_parms* parms) {
4186 int card;
4187 if ((str_parms_get_int(parms, "card", &card) >= 0) &&
4188 !audio_extn_usb_alive(card)) {
4189 return card;
4190 }
4191 return -ENODEV;
4192}
4193
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004194static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
4195{
4196 struct stream_out *out = (struct stream_out *)stream;
4197 struct audio_device *adev = out->dev;
4198 struct str_parms *parms;
4199 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004200 int ret = 0, val = 0, err;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304201 bool bypass_a2dp = false;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004202 bool reconfig = false;
4203 unsigned long service_interval = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004204
sangwoobc677242013-08-08 16:53:43 +09004205 ALOGD("%s: enter: usecase(%d: %s) kvpairs: %s",
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004206 __func__, out->usecase, use_case_table[out->usecase], kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004207 parms = str_parms_create_str(kvpairs);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304208 if (!parms)
4209 goto error;
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08004210 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
4211 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004212 val = atoi(value);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004213 lock_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004214 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004215
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004216 /*
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004217 * When HDMI cable is unplugged the music playback is paused and
4218 * the policy manager sends routing=0. But the audioflinger continues
4219 * to write data until standby time (3sec). As the HDMI core is
4220 * turned off, the write gets blocked.
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004221 * Avoid this by routing audio to speaker until standby.
4222 */
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004223 if ((out->devices == AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
4224 (val == AUDIO_DEVICE_NONE) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304225 !audio_extn_passthru_is_passthrough_stream(out) &&
Weiyin Jiang4256eeb2016-05-19 13:28:30 +08004226 (platform_get_edid_info(adev->platform) != 0) /* HDMI disconnected */) {
4227 val = AUDIO_DEVICE_OUT_SPEAKER;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004228 }
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304229 /*
4230 * When A2DP is disconnected the
4231 * music playback is paused and the policy manager sends routing=0
Florian Pfister1a84f312018-07-19 14:38:18 +02004232 * But the audioflinger continues to write data until standby time
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304233 * (3sec). As BT is turned off, the write gets blocked.
4234 * Avoid this by routing audio to speaker until standby.
4235 */
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07004236 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Aniket Kumar Lata1fb11cb2017-09-08 13:48:55 -07004237 (val == AUDIO_DEVICE_NONE) &&
Aniket Kumar Lata2cf6a922019-05-07 17:01:43 -07004238 !audio_extn_a2dp_source_is_ready() &&
4239 !adev->bt_sco_on) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05304240 val = AUDIO_DEVICE_OUT_SPEAKER;
4241 }
Sharad Sangled0a50b22018-04-05 23:28:32 +05304242 /*
4243 * When USB headset is disconnected the music platback paused
4244 * and the policy manager send routing=0. But if the USB is connected
4245 * back before the standby time, AFE is not closed and opened
4246 * when USB is connected back. So routing to speker will guarantee
4247 * AFE reconfiguration and AFE will be opend once USB is connected again
4248 */
4249 if ((out->devices & AUDIO_DEVICE_OUT_ALL_USB) &&
4250 (val == AUDIO_DEVICE_NONE) &&
4251 !audio_extn_usb_connected(parms)) {
4252 val = AUDIO_DEVICE_OUT_SPEAKER;
4253 }
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304254 /* To avoid a2dp to sco overlapping / BT device improper state
4255 * check with BT lib about a2dp streaming support before routing
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304256 */
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304257 if (val & AUDIO_DEVICE_OUT_ALL_A2DP) {
Florian Pfister1a84f312018-07-19 14:38:18 +02004258 if (!audio_extn_a2dp_source_is_ready()) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004259 if (val &
4260 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE)) {
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304261 //combo usecase just by pass a2dp
4262 ALOGW("%s: A2DP profile is not ready,routing to speaker only", __func__);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304263 bypass_a2dp = true;
Preetam Singh Ranawata1849ba2017-02-06 14:10:11 +05304264 } else {
4265 ALOGE("%s: A2DP profile is not ready,ignoring routing request", __func__);
4266 /* update device to a2dp and don't route as BT returned error
4267 * However it is still possible a2dp routing called because
4268 * of current active device disconnection (like wired headset)
4269 */
4270 out->devices = val;
4271 pthread_mutex_unlock(&out->lock);
4272 pthread_mutex_unlock(&adev->lock);
4273 goto error;
4274 }
4275 }
Naresh Tanniru03f9dd52016-10-19 18:46:22 +05304276 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004277
4278 audio_devices_t new_dev = val;
4279
4280 // Workaround: If routing to an non existing usb device, fail gracefully
4281 // The routing request will otherwise block during 10 second
4282 int card;
4283 if (audio_is_usb_out_device(new_dev) &&
4284 (card = get_alive_usb_card(parms)) >= 0) {
4285
4286 ALOGW("out_set_parameters() ignoring rerouting to non existing USB card %d", card);
4287 pthread_mutex_unlock(&adev->lock);
4288 pthread_mutex_unlock(&out->lock);
4289 ret = -ENOSYS;
4290 goto routing_fail;
4291 }
4292
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004293 /*
4294 * select_devices() call below switches all the usecases on the same
4295 * backend to the new device. Refer to check_usecases_codec_backend() in
4296 * the select_devices(). But how do we undo this?
4297 *
4298 * For example, music playback is active on headset (deep-buffer usecase)
4299 * and if we go to ringtones and select a ringtone, low-latency usecase
4300 * will be started on headset+speaker. As we can't enable headset+speaker
4301 * and headset devices at the same time, select_devices() switches the music
4302 * playback to headset+speaker while starting low-lateny usecase for ringtone.
4303 * So when the ringtone playback is completed, how do we undo the same?
4304 *
4305 * We are relying on the out_set_parameters() call on deep-buffer output,
4306 * once the ringtone playback is ended.
4307 * NOTE: We should not check if the current devices are same as new devices.
4308 * Because select_devices() must be called to switch back the music
4309 * playback to headset.
4310 */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004311 if (val != 0) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004312 audio_devices_t new_dev = val;
4313 bool same_dev = out->devices == new_dev;
4314 out->devices = new_dev;
Ravi Kumar Alamanda71c84b72013-03-10 23:50:28 -07004315
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004316 if (output_drives_call(adev, out)) {
kunleiz61b9c2e2017-11-01 13:47:23 +08004317 if (!voice_is_call_state_active(adev)) {
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004318 if (adev->mode == AUDIO_MODE_IN_CALL) {
4319 adev->current_call_output = out;
Garmond Leung5fd0b552018-04-17 11:56:12 -07004320 if (audio_is_usb_out_device(out->devices & AUDIO_DEVICE_OUT_ALL_USB)) {
4321 service_interval = audio_extn_usb_find_service_interval(true, true /*playback*/);
4322 audio_extn_usb_set_service_interval(true /*playback*/,
4323 service_interval,
4324 &reconfig);
4325 ALOGD("%s, svc_int(%ld),reconfig(%d)",__func__,service_interval, reconfig);
4326 }
4327 ret = voice_start_call(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004328 }
4329 } else {
4330 adev->current_call_output = out;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07004331 voice_update_devices_for_all_voice_usecases(adev);
Ravi Kumar Alamandabe149392014-10-20 17:07:43 -07004332 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004333 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004334
4335 if (!out->standby) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004336 if (!same_dev) {
4337 ALOGV("update routing change");
Sudheer Papothi80266982016-08-16 02:36:18 +05304338 audio_extn_perf_lock_acquire(&adev->perf_lock_handle, 0,
4339 adev->perf_lock_opts,
4340 adev->perf_lock_opts_size);
Haynes Mathew George822b5492016-07-01 16:57:24 -07004341 if (adev->adm_on_routing_change)
4342 adev->adm_on_routing_change(adev->adm_data,
4343 out->handle);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004344 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304345 if (!bypass_a2dp) {
4346 select_devices(adev, out->usecase);
4347 } else {
Aalique Grahame22e49102018-12-18 14:23:57 -08004348 if (new_dev & AUDIO_DEVICE_OUT_SPEAKER_SAFE)
4349 out->devices = AUDIO_DEVICE_OUT_SPEAKER_SAFE;
4350 else
4351 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304352 select_devices(adev, out->usecase);
4353 out->devices = new_dev;
4354 }
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004355
4356 if (!same_dev) {
4357 // on device switch force swap, lower functions will make sure
4358 // to check if swap is allowed or not.
4359 platform_set_swap_channels(adev, true);
Sudheer Papothi80266982016-08-16 02:36:18 +05304360 audio_extn_perf_lock_release(&adev->perf_lock_handle);
Vignesh Kulothungan3b5fae52017-09-25 12:16:30 -07004361 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304362 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
4363 out->a2dp_compress_mute &&
Florian Pfister1a84f312018-07-19 14:38:18 +02004364 (!(out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) || audio_extn_a2dp_source_is_ready())) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304365 pthread_mutex_lock(&out->compr_mute_lock);
4366 out->a2dp_compress_mute = false;
4367 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
4368 pthread_mutex_unlock(&out->compr_mute_lock);
kunleizba786432018-01-26 15:31:59 +08004369 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
4370 out_set_voip_volume(&out->stream, out->volume_l, out->volume_r);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304371 }
Shiv Maliyappanahalli6b32c4c2015-11-04 18:10:20 -08004372 }
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08004373 }
4374
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004375 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08004376 pthread_mutex_unlock(&out->lock);
Aalique Grahame22e49102018-12-18 14:23:57 -08004377
4378 /*handles device and call state changes*/
4379 audio_extn_extspk_update(adev->extspk);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004380 }
Kevin Rocardfce19002017-08-07 19:21:36 -07004381 routing_fail:
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004382
4383 if (out == adev->primary_output) {
4384 pthread_mutex_lock(&adev->lock);
4385 audio_extn_set_parameters(adev, parms);
4386 pthread_mutex_unlock(&adev->lock);
4387 }
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004388 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07004389 lock_output_stream(out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004390 parse_compress_metadata(out, parms);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08004391
4392 audio_extn_dts_create_state_notifier_node(out->usecase);
4393 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
4394 popcount(out->channel_mask),
4395 out->playback_started);
4396
Krishnankutty Kolathappillyeb78be72013-12-15 12:03:07 -08004397 pthread_mutex_unlock(&out->lock);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07004398 }
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07004399
Surendar Karkaf51b5842018-04-26 11:28:38 +05304400 err = str_parms_get_str(parms, AUDIO_PARAMETER_DUAL_MONO, value,
4401 sizeof(value));
4402 if (err >= 0) {
4403 if (!strncmp("true", value, sizeof("true")) || atoi(value))
4404 audio_extn_send_dual_mono_mixing_coefficients(out);
4405 }
4406
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304407 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
4408 if (err >= 0) {
4409 strlcpy(out->profile, value, sizeof(out->profile));
4410 ALOGV("updating stream profile with value '%s'", out->profile);
4411 lock_output_stream(out);
4412 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
4413 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07004414 out->devices, out->flags, out->hal_op_format,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05304415 out->sample_rate, out->bit_width,
4416 out->channel_mask, out->profile,
4417 &out->app_type_cfg);
4418 pthread_mutex_unlock(&out->lock);
4419 }
4420
Alexy Joseph98988832017-01-13 14:56:59 -08004421 //suspend, resume handling block
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004422 //remove QOS only if vendor.audio.hal.dynamic.qos.config.supported is set to true
4423 // and vendor.audio.hal.output.suspend.supported is set to true
4424 if (out->hal_output_suspend_supported && out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08004425 //check suspend parameter only for low latency and if the property
4426 //is enabled
4427 if (str_parms_get_str(parms, "suspend_playback", value, sizeof(value)) >= 0) {
4428 ALOGI("%s: got suspend_playback %s", __func__, value);
4429 lock_output_stream(out);
4430 if (!strncmp(value, "false", 5)) {
4431 //suspend_playback=false is supposed to set QOS value back to 75%
4432 //the mixer control sent with value Enable will achieve that
4433 ret = audio_route_apply_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4434 } else if (!strncmp (value, "true", 4)) {
4435 //suspend_playback=true is supposed to remove QOS value
4436 //resetting the mixer control will set the default value
4437 //for the mixer control which is Disable and this removes the QOS vote
4438 ret = audio_route_reset_and_update_path(adev->audio_route, out->pm_qos_mixer_path);
4439 } else {
4440 ALOGE("%s: Wrong value sent for suspend_playback, expected true/false,"
4441 " got %s", __func__, value);
4442 ret = -1;
4443 }
4444
4445 if (ret != 0) {
4446 ALOGE("%s: %s mixer ctl failed with %d, ignore suspend/resume setparams",
4447 __func__, out->pm_qos_mixer_path, ret);
4448 }
4449
4450 pthread_mutex_unlock(&out->lock);
4451 }
4452 }
4453 //end suspend, resume handling block
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004454 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05304455error:
Eric Laurent994a6932013-07-17 11:51:42 -07004456 ALOGV("%s: exit: code(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004457 return ret;
4458}
4459
Paul McLeana50b7332018-12-17 08:24:21 -07004460static int in_set_microphone_direction(const struct audio_stream_in *stream,
4461 audio_microphone_direction_t dir) {
justinweng20fb6d82019-02-21 18:49:00 -07004462 struct stream_in *in = (struct stream_in *)stream;
4463
4464 ALOGVV("%s: standby %d source %d dir %d", __func__, in->standby, in->source, dir);
4465
4466 in->direction = dir;
4467
4468 if (in->standby)
4469 return 0;
4470
4471 return audio_extn_audiozoom_set_microphone_direction(in, dir);
Paul McLeana50b7332018-12-17 08:24:21 -07004472}
4473
4474static int in_set_microphone_field_dimension(const struct audio_stream_in *stream, float zoom) {
justinweng20fb6d82019-02-21 18:49:00 -07004475 struct stream_in *in = (struct stream_in *)stream;
4476
4477 ALOGVV("%s: standby %d source %d zoom %f", __func__, in->standby, in->source, zoom);
4478
4479 if (zoom > 1.0 || zoom < -1.0)
4480 return -EINVAL;
4481
4482 in->zoom = zoom;
4483
4484 if (in->standby)
4485 return 0;
4486
4487 return audio_extn_audiozoom_set_microphone_field_dimension(in, zoom);
Paul McLeana50b7332018-12-17 08:24:21 -07004488}
4489
4490
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004491static bool stream_get_parameter_channels(struct str_parms *query,
4492 struct str_parms *reply,
4493 audio_channel_mask_t *supported_channel_masks) {
4494 int ret = -1;
4495 char value[512];
4496 bool first = true;
4497 size_t i, j;
4498
4499 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS)) {
4500 ret = 0;
4501 value[0] = '\0';
4502 i = 0;
4503 while (supported_channel_masks[i] != 0) {
4504 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4505 if (channels_name_to_enum_table[j].value == supported_channel_masks[i]) {
4506 if (!first)
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304507 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004508
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304509 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004510 first = false;
4511 break;
4512 }
4513 }
4514 i++;
4515 }
4516 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4517 }
4518 return ret == 0;
4519}
4520
4521static bool stream_get_parameter_formats(struct str_parms *query,
4522 struct str_parms *reply,
4523 audio_format_t *supported_formats) {
4524 int ret = -1;
4525 char value[256];
4526 size_t i, j;
4527 bool first = true;
4528
4529 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS)) {
4530 ret = 0;
4531 value[0] = '\0';
4532 i = 0;
4533 while (supported_formats[i] != 0) {
4534 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4535 if (formats_name_to_enum_table[j].value == supported_formats[i]) {
4536 if (!first) {
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304537 strlcat(value, "|", sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004538 }
Satya Krishna Pindiprolib22ac722017-10-09 15:44:16 +05304539 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004540 first = false;
4541 break;
4542 }
4543 }
4544 i++;
4545 }
4546 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
4547 }
4548 return ret == 0;
4549}
4550
4551static bool stream_get_parameter_rates(struct str_parms *query,
4552 struct str_parms *reply,
4553 uint32_t *supported_sample_rates) {
4554
4555 int i;
4556 char value[256];
4557 int ret = -1;
4558 if (str_parms_has_key(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES)) {
4559 ret = 0;
4560 value[0] = '\0';
4561 i=0;
4562 int cursor = 0;
4563 while (supported_sample_rates[i]) {
4564 int avail = sizeof(value) - cursor;
4565 ret = snprintf(value + cursor, avail, "%s%d",
4566 cursor > 0 ? "|" : "",
4567 supported_sample_rates[i]);
4568 if (ret < 0 || ret >= avail) {
4569 // if cursor is at the last element of the array
4570 // overwrite with \0 is duplicate work as
4571 // snprintf already put a \0 in place.
4572 // else
4573 // we had space to write the '|' at value[cursor]
4574 // (which will be overwritten) or no space to fill
4575 // the first element (=> cursor == 0)
4576 value[cursor] = '\0';
4577 break;
4578 }
4579 cursor += ret;
4580 ++i;
4581 }
4582 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES,
4583 value);
4584 }
4585 return ret >= 0;
4586}
4587
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004588static char* out_get_parameters(const struct audio_stream *stream, const char *keys)
4589{
4590 struct stream_out *out = (struct stream_out *)stream;
4591 struct str_parms *query = str_parms_create_str(keys);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004592 char *str = (char*) NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004593 char value[256];
4594 struct str_parms *reply = str_parms_create();
4595 size_t i, j;
4596 int ret;
4597 bool first = true;
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004598
4599 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004600 if (reply) {
4601 str_parms_destroy(reply);
4602 }
4603 if (query) {
4604 str_parms_destroy(query);
4605 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07004606 ALOGE("out_get_parameters: failed to allocate mem for query or reply");
4607 return NULL;
4608 }
4609
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004610 ALOGV("%s: %s enter: keys - %s", __func__, use_case_table[out->usecase], keys);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004611 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value, sizeof(value));
4612 if (ret >= 0) {
4613 value[0] = '\0';
4614 i = 0;
4615 while (out->supported_channel_masks[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004616 for (j = 0; j < ARRAY_SIZE(channels_name_to_enum_table); j++) {
4617 if (channels_name_to_enum_table[j].value == out->supported_channel_masks[i]) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004618 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004619 strlcat(value, "|", sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004620 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004621 strlcat(value, channels_name_to_enum_table[j].name, sizeof(value));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004622 first = false;
4623 break;
4624 }
4625 }
4626 i++;
4627 }
4628 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_CHANNELS, value);
4629 str = str_parms_to_str(reply);
4630 } else {
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08004631 voice_extn_out_get_parameters(out, query, reply);
4632 str = str_parms_to_str(reply);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004633 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004634
Alexy Joseph62142aa2015-11-16 15:10:34 -08004635
4636 ret = str_parms_get_str(query, "is_direct_pcm_track", value, sizeof(value));
4637 if (ret >= 0) {
4638 value[0] = '\0';
Dhananjay Kumarac341582017-02-23 23:42:25 +05304639 if (out->flags & AUDIO_OUTPUT_FLAG_DIRECT &&
4640 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Alexy Joseph62142aa2015-11-16 15:10:34 -08004641 ALOGV("in direct_pcm");
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05304642 strlcat(value, "true", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004643 } else {
4644 ALOGV("not in direct_pcm");
Sharad Sangle3dd5a4a2015-12-10 18:39:17 +05304645 strlcat(value, "false", sizeof(value));
Alexy Joseph62142aa2015-11-16 15:10:34 -08004646 }
4647 str_parms_add_str(reply, "is_direct_pcm_track", value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004648 if (str)
4649 free(str);
Alexy Joseph62142aa2015-11-16 15:10:34 -08004650 str = str_parms_to_str(reply);
4651 }
4652
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004653 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value, sizeof(value));
4654 if (ret >= 0) {
4655 value[0] = '\0';
4656 i = 0;
4657 first = true;
4658 while (out->supported_formats[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004659 for (j = 0; j < ARRAY_SIZE(formats_name_to_enum_table); j++) {
4660 if (formats_name_to_enum_table[j].value == out->supported_formats[i]) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004661 if (!first) {
Apoorv Raghuvanshi8880cac2015-02-06 15:33:49 -08004662 strlcat(value, "|", sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004663 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004664 strlcat(value, formats_name_to_enum_table[j].name, sizeof(value));
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004665 first = false;
4666 break;
4667 }
4668 }
4669 i++;
4670 }
4671 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_FORMATS, value);
Alexy Josephaee4fdd2016-01-29 13:02:07 -08004672 if (str)
4673 free(str);
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004674 str = str_parms_to_str(reply);
4675 }
Mingming Yin3a941d42016-02-17 18:08:05 -08004676
4677 ret = str_parms_get_str(query, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value, sizeof(value));
4678 if (ret >= 0) {
4679 value[0] = '\0';
4680 i = 0;
4681 first = true;
4682 while (out->supported_sample_rates[i] != 0) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004683 for (j = 0; j < ARRAY_SIZE(out_sample_rates_name_to_enum_table); j++) {
4684 if (out_sample_rates_name_to_enum_table[j].value == out->supported_sample_rates[i]) {
Mingming Yin3a941d42016-02-17 18:08:05 -08004685 if (!first) {
4686 strlcat(value, "|", sizeof(value));
4687 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07004688 strlcat(value, out_sample_rates_name_to_enum_table[j].name, sizeof(value));
Mingming Yin3a941d42016-02-17 18:08:05 -08004689 first = false;
4690 break;
4691 }
4692 }
4693 i++;
4694 }
4695 str_parms_add_str(reply, AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES, value);
4696 if (str)
4697 free(str);
4698 str = str_parms_to_str(reply);
4699 }
4700
Alexy Joseph98988832017-01-13 14:56:59 -08004701 if (str_parms_get_str(query, "supports_hw_suspend", value, sizeof(value)) >= 0) {
4702 //only low latency track supports suspend_resume
4703 str_parms_add_int(reply, "supports_hw_suspend",
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08004704 (out->hal_output_suspend_supported));
Alexy Joseph98988832017-01-13 14:56:59 -08004705 if (str)
4706 free(str);
4707 str = str_parms_to_str(reply);
4708 }
4709
4710
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004711 str_parms_destroy(query);
4712 str_parms_destroy(reply);
Eric Laurent994a6932013-07-17 11:51:42 -07004713 ALOGV("%s: exit: returns - %s", __func__, str);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004714 return str;
4715}
4716
4717static uint32_t out_get_latency(const struct audio_stream_out *stream)
4718{
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004719 uint32_t period_ms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004720 struct stream_out *out = (struct stream_out *)stream;
Alexy Josephaa54c872014-12-03 02:46:47 -08004721 uint32_t latency = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004722
Alexy Josephaa54c872014-12-03 02:46:47 -08004723 if (is_offload_usecase(out->usecase)) {
Manish Dewangan07de2142017-02-27 19:27:20 +05304724 lock_output_stream(out);
4725 latency = audio_extn_utils_compress_get_dsp_latency(out);
4726 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07004727 } else if ((out->realtime) ||
4728 (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07004729 // since the buffer won't be filled up faster than realtime,
4730 // return a smaller number
4731 if (out->config.rate)
4732 period_ms = (out->af_period_multiplier * out->config.period_size *
4733 1000) / (out->config.rate);
4734 else
4735 period_ms = 0;
4736 latency = period_ms + platform_render_latency(out->usecase)/1000;
Alexy Josephaa54c872014-12-03 02:46:47 -08004737 } else {
4738 latency = (out->config.period_count * out->config.period_size * 1000) /
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004739 (out->config.rate);
Alexy Josephaa54c872014-12-03 02:46:47 -08004740 }
4741
yidongh0515e042017-07-06 15:00:34 +08004742 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices)
Aniket Kumar Latad5972fa2017-02-08 13:53:48 -08004743 latency += audio_extn_a2dp_get_encoder_latency();
4744
Anish Kumar50ebcbf2014-12-09 04:01:39 +05304745 ALOGV("%s: Latency %d", __func__, latency);
Alexy Josephaa54c872014-12-03 02:46:47 -08004746 return latency;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004747}
4748
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304749static float AmpToDb(float amplification)
4750{
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304751 float db = DSD_VOLUME_MIN_DB;
4752 if (amplification > 0) {
4753 db = 20 * log10(amplification);
4754 if(db < DSD_VOLUME_MIN_DB)
4755 return DSD_VOLUME_MIN_DB;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304756 }
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05304757 return db;
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304758}
4759
Arun Mirpuri5d170872019-03-26 13:21:31 -07004760static int out_set_mmap_volume(struct audio_stream_out *stream, float left,
4761 float right)
4762{
4763 struct stream_out *out = (struct stream_out *)stream;
4764 long volume = 0;
4765 char mixer_ctl_name[128] = "";
4766 struct audio_device *adev = out->dev;
4767 struct mixer_ctl *ctl = NULL;
4768 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4769 PCM_PLAYBACK);
4770
4771 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4772 "Playback %d Volume", pcm_device_id);
4773 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4774 if (!ctl) {
4775 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4776 __func__, mixer_ctl_name);
4777 return -EINVAL;
4778 }
4779 if (left != right)
4780 ALOGW("%s: Left and right channel volume mismatch:%f,%f",
4781 __func__, left, right);
4782 volume = (long)(left * (MMAP_PLAYBACK_VOLUME_MAX*1.0));
4783 if (mixer_ctl_set_value(ctl, 0, volume) < 0){
4784 ALOGE("%s:ctl for mixer cmd - %s, volume %ld returned error",
4785 __func__, mixer_ctl_name, volume);
4786 return -EINVAL;
4787 }
4788 return 0;
4789}
4790
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304791static int out_set_compr_volume(struct audio_stream_out *stream, float left,
4792 float right)
4793{
4794 struct stream_out *out = (struct stream_out *)stream;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304795 long volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304796 char mixer_ctl_name[128];
4797 struct audio_device *adev = out->dev;
4798 struct mixer_ctl *ctl;
4799 int pcm_device_id = platform_get_pcm_device_id(out->usecase,
4800 PCM_PLAYBACK);
4801
4802 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
4803 "Compress Playback %d Volume", pcm_device_id);
4804 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4805 if (!ctl) {
4806 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4807 __func__, mixer_ctl_name);
4808 return -EINVAL;
4809 }
4810 ALOGE("%s:ctl for mixer cmd - %s, left %f, right %f",
4811 __func__, mixer_ctl_name, left, right);
4812 volume[0] = (int)(left * COMPRESS_PLAYBACK_VOLUME_MAX);
4813 volume[1] = (int)(right * COMPRESS_PLAYBACK_VOLUME_MAX);
4814 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4815
4816 return 0;
4817}
4818
Zhou Song2b8f28f2017-09-11 10:51:38 +08004819static int out_set_voip_volume(struct audio_stream_out *stream, float left,
4820 float right)
4821{
4822 struct stream_out *out = (struct stream_out *)stream;
4823 char mixer_ctl_name[] = "App Type Gain";
4824 struct audio_device *adev = out->dev;
4825 struct mixer_ctl *ctl;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304826 long set_values[4];
Zhou Song2b8f28f2017-09-11 10:51:38 +08004827
4828 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4829 if (!ctl) {
4830 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4831 __func__, mixer_ctl_name);
4832 return -EINVAL;
4833 }
4834
4835 set_values[0] = 0; //0: Rx Session 1:Tx Session
4836 set_values[1] = out->app_type_cfg.app_type;
Manish Dewangan338c50a2017-09-12 15:22:03 +05304837 set_values[2] = (long)(left * VOIP_PLAYBACK_VOLUME_MAX);
4838 set_values[3] = (long)(right * VOIP_PLAYBACK_VOLUME_MAX);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004839
4840 mixer_ctl_set_array(ctl, set_values, ARRAY_SIZE(set_values));
4841 return 0;
4842}
4843
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304844static int out_set_pcm_volume(struct audio_stream_out *stream, float left,
4845 float right)
4846{
4847 struct stream_out *out = (struct stream_out *)stream;
4848 /* Volume control for pcm playback */
4849 if (left != right) {
4850 return -EINVAL;
4851 } else {
4852 char mixer_ctl_name[128];
4853 struct audio_device *adev = out->dev;
4854 struct mixer_ctl *ctl;
4855 int pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
4856 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Playback %d Volume", pcm_device_id);
4857 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4858 if (!ctl) {
4859 ALOGE("%s : Could not get ctl for mixer cmd - %s", __func__, mixer_ctl_name);
4860 return -EINVAL;
4861 }
4862
4863 int volume = (int) (left * PCM_PLAYBACK_VOLUME_MAX);
4864 int ret = mixer_ctl_set_value(ctl, 0, volume);
4865 if (ret < 0) {
4866 ALOGE("%s: Could not set ctl, error:%d ", __func__, ret);
4867 return -EINVAL;
4868 }
4869
4870 ALOGV("%s : Pcm set volume value %d left %f", __func__, volume, left);
4871
4872 return 0;
4873 }
4874}
4875
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004876static int out_set_volume(struct audio_stream_out *stream, float left,
4877 float right)
4878{
Eric Laurenta9024de2013-04-04 09:19:12 -07004879 struct stream_out *out = (struct stream_out *)stream;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004880 int volume[2];
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304881 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004882
Arun Mirpuri5d170872019-03-26 13:21:31 -07004883 ALOGD("%s: called with left_vol=%f, right_vol=%f", __func__, left, right);
Eric Laurenta9024de2013-04-04 09:19:12 -07004884 if (out->usecase == USECASE_AUDIO_PLAYBACK_MULTI_CH) {
4885 /* only take left channel into account: the API is for stereo anyway */
4886 out->muted = (left == 0.0f);
4887 return 0;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07004888 } else if (is_offload_usecase(out->usecase)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304889 if (audio_extn_passthru_is_passthrough_stream(out)) {
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004890 /*
4891 * Set mute or umute on HDMI passthrough stream.
4892 * Only take left channel into account.
4893 * Mute is 0 and unmute 1
4894 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05304895 audio_extn_passthru_set_volume(out, (left == 0.0f));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304896 } else if (out->format == AUDIO_FORMAT_DSD){
4897 char mixer_ctl_name[128] = "DSD Volume";
4898 struct audio_device *adev = out->dev;
4899 struct mixer_ctl *ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
4900
4901 if (!ctl) {
4902 ALOGE("%s: Could not get ctl for mixer cmd - %s",
4903 __func__, mixer_ctl_name);
4904 return -EINVAL;
4905 }
Manish Dewangan338c50a2017-09-12 15:22:03 +05304906 volume[0] = (long)(AmpToDb(left));
4907 volume[1] = (long)(AmpToDb(right));
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05304908 mixer_ctl_set_array(ctl, volume, sizeof(volume)/sizeof(volume[0]));
4909 return 0;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07004910 } else {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304911 pthread_mutex_lock(&out->compr_mute_lock);
Arun Mirpuri5d170872019-03-26 13:21:31 -07004912 ALOGV("%s: compress mute %d", __func__, out->a2dp_compress_mute);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05304913 if (!out->a2dp_compress_mute)
4914 ret = out_set_compr_volume(stream, left, right);
4915 out->volume_l = left;
4916 out->volume_r = right;
4917 pthread_mutex_unlock(&out->compr_mute_lock);
4918 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004919 }
Vikram Panduranga93f080e2017-06-07 18:16:14 -07004920 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP) {
Aalique Grahame22e49102018-12-18 14:23:57 -08004921 out->app_type_cfg.gain[0] = (int)(left * VOIP_PLAYBACK_VOLUME_MAX);
4922 out->app_type_cfg.gain[1] = (int)(right * VOIP_PLAYBACK_VOLUME_MAX);
4923 if (!out->standby) {
4924 audio_extn_utils_send_app_type_gain(out->dev,
4925 out->app_type_cfg.app_type,
4926 &out->app_type_cfg.gain[0]);
Zhou Song2b8f28f2017-09-11 10:51:38 +08004927 ret = out_set_voip_volume(stream, left, right);
Aalique Grahame22e49102018-12-18 14:23:57 -08004928 }
Zhou Song2b8f28f2017-09-11 10:51:38 +08004929 out->volume_l = left;
4930 out->volume_r = right;
4931 return ret;
Arun Mirpuri5d170872019-03-26 13:21:31 -07004932 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
4933 ALOGV("%s: MMAP set volume called", __func__);
4934 if (!out->standby)
4935 ret = out_set_mmap_volume(stream, left, right);
4936 out->volume_l = left;
4937 out->volume_r = right;
4938 return ret;
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304939 } else if (out->usecase == USECASE_AUDIO_PLAYBACK_LOW_LATENCY ||
Ramu Gottipati36547092018-12-28 11:32:09 +05304940 out->usecase == USECASE_AUDIO_PLAYBACK_DEEP_BUFFER ||
4941 out->usecase == USECASE_AUDIO_PLAYBACK_ULL) {
Ramu Gottipati97bdcfb2018-04-13 17:58:24 +05304942 /* Volume control for pcm playback */
4943 if (!out->standby)
4944 ret = out_set_pcm_volume(stream, left, right);
4945 else
4946 out->apply_volume = true;
4947
4948 out->volume_l = left;
4949 out->volume_r = right;
4950 return ret;
Eric Laurenta9024de2013-04-04 09:19:12 -07004951 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07004952
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08004953 return -ENOSYS;
4954}
4955
Zhou Songc9672822017-08-16 16:01:39 +08004956static void update_frames_written(struct stream_out *out, size_t bytes)
4957{
4958 size_t bpf = 0;
4959
4960 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
4961 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD))
4962 bpf = 1;
4963 else if (!is_offload_usecase(out->usecase))
4964 bpf = audio_bytes_per_sample(out->format) *
4965 audio_channel_count_from_out_mask(out->channel_mask);
Zhou Song48453a02018-01-10 17:50:59 +08004966
4967 pthread_mutex_lock(&out->position_query_lock);
4968 if (bpf != 0) {
Zhou Songc9672822017-08-16 16:01:39 +08004969 out->written += bytes / bpf;
Zhou Song48453a02018-01-10 17:50:59 +08004970 clock_gettime(CLOCK_MONOTONIC, &out->writeAt);
4971 }
4972 pthread_mutex_unlock(&out->position_query_lock);
Zhou Songc9672822017-08-16 16:01:39 +08004973}
4974
Vignesh Kulothungana6927272019-02-20 15:17:07 -08004975int split_and_write_audio_haptic_data(struct stream_out *out,
4976 const void *buffer, size_t bytes_to_write)
4977{
4978 struct audio_device *adev = out->dev;
4979
4980 int ret = 0;
4981 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
4982 size_t bytes_per_sample = audio_bytes_per_sample(out->format);
4983 size_t frame_size = channel_count * bytes_per_sample;
4984 size_t frame_count = bytes_to_write / frame_size;
4985
4986 bool force_haptic_path =
4987 property_get_bool("vendor.audio.test_haptic", false);
4988
4989 // extract Haptics data from Audio buffer
4990 bool alloc_haptic_buffer = false;
4991 int haptic_channel_count = adev->haptics_config.channels;
4992 size_t haptic_frame_size = bytes_per_sample * haptic_channel_count;
4993 size_t audio_frame_size = frame_size - haptic_frame_size;
4994 size_t total_haptic_buffer_size = frame_count * haptic_frame_size;
4995
4996 if (adev->haptic_buffer == NULL) {
4997 alloc_haptic_buffer = true;
4998 } else if (adev->haptic_buffer_size < total_haptic_buffer_size) {
4999 free(adev->haptic_buffer);
5000 adev->haptic_buffer_size = 0;
5001 alloc_haptic_buffer = true;
5002 }
5003
5004 if (alloc_haptic_buffer) {
5005 adev->haptic_buffer = (uint8_t *)calloc(1, total_haptic_buffer_size);
Mingshu Pang1513f972019-05-24 12:43:51 +08005006 if(adev->haptic_buffer == NULL) {
5007 ALOGE("%s: failed to allocate mem for dev->haptic_buffer", __func__);
5008 return -ENOMEM;
5009 }
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005010 adev->haptic_buffer_size = total_haptic_buffer_size;
5011 }
5012
5013 size_t src_index = 0, aud_index = 0, hap_index = 0;
5014 uint8_t *audio_buffer = (uint8_t *)buffer;
5015 uint8_t *haptic_buffer = adev->haptic_buffer;
5016
5017 // This is required for testing only. This works for stereo data only.
5018 // One channel is fed to audio stream and other to haptic stream for testing.
5019 if (force_haptic_path)
5020 audio_frame_size = haptic_frame_size = bytes_per_sample;
5021
5022 for (size_t i = 0; i < frame_count; i++) {
5023 memcpy(audio_buffer + aud_index, audio_buffer + src_index,
5024 audio_frame_size);
5025 aud_index += audio_frame_size;
5026 src_index += audio_frame_size;
5027
5028 if (adev->haptic_pcm)
5029 memcpy(haptic_buffer + hap_index, audio_buffer + src_index,
5030 haptic_frame_size);
5031 hap_index += haptic_frame_size;
5032 src_index += haptic_frame_size;
5033
5034 // This is required for testing only.
5035 // Discard haptic channel data.
5036 if (force_haptic_path)
5037 src_index += haptic_frame_size;
5038 }
5039
5040 // write to audio pipeline
5041 ret = pcm_write(out->pcm, (void *)audio_buffer,
5042 frame_count * audio_frame_size);
5043
5044 // write to haptics pipeline
5045 if (adev->haptic_pcm)
5046 ret = pcm_write(adev->haptic_pcm, (void *)adev->haptic_buffer,
5047 frame_count * haptic_frame_size);
5048
5049 return ret;
5050}
5051
Aalique Grahame22e49102018-12-18 14:23:57 -08005052#ifdef NO_AUDIO_OUT
5053static ssize_t out_write_for_no_output(struct audio_stream_out *stream,
5054 const void *buffer __unused, size_t bytes)
5055{
5056 struct stream_out *out = (struct stream_out *)stream;
5057
5058 /* No Output device supported other than BT for playback.
5059 * Sleep for the amount of buffer duration
5060 */
5061 lock_output_stream(out);
5062 usleep(bytes * 1000000 / audio_stream_out_frame_size(
5063 (const struct audio_stream_out *)&out->stream) /
5064 out_get_sample_rate(&out->stream.common));
5065 pthread_mutex_unlock(&out->lock);
5066 return bytes;
5067}
5068#endif
5069
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005070static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
5071 size_t bytes)
5072{
5073 struct stream_out *out = (struct stream_out *)stream;
5074 struct audio_device *adev = out->dev;
Eric Laurent6e895242013-09-05 16:10:57 -07005075 ssize_t ret = 0;
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305076 int channels = 0;
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005077 const size_t frame_size = audio_stream_out_frame_size(stream);
5078 const size_t frames = (frame_size != 0) ? bytes / frame_size : bytes;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305079 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005080
Haynes Mathew George380745d2017-10-04 15:27:45 -07005081 ATRACE_BEGIN("out_write");
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005082 lock_output_stream(out);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305083
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305084 if (CARD_STATUS_OFFLINE == out->card_status) {
Zhou Song0b2e5dc2015-03-16 14:41:38 +08005085
Dhananjay Kumarac341582017-02-23 23:42:25 +05305086 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305087 /*during SSR for compress usecase we should return error to flinger*/
Naresh Tanniru80659832014-06-04 18:17:56 +05305088 ALOGD(" copl %s: sound card is not active/SSR state", __func__);
5089 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005090 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305091 return -ENETRESET;
Ashish Jainbbce4322016-02-16 13:25:27 +05305092 } else {
Ashish Jainbbce4322016-02-16 13:25:27 +05305093 ALOGD(" %s: sound card is not active/SSR state", __func__);
5094 ret= -EIO;
5095 goto exit;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305096 }
5097 }
5098
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305099 if (audio_extn_passthru_should_drop_data(out)) {
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305100 ALOGV(" %s : Drop data as compress passthrough session is going on", __func__);
Ashish Jaind84fd6a2016-07-27 12:33:25 +05305101 ret = -EIO;
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05305102 goto exit;
5103 }
5104
Haynes Mathew George16081042017-05-31 17:16:49 -07005105 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP) {
5106 ret = -EINVAL;
5107 goto exit;
5108 }
5109
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305110 if ((out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL) &&
5111 !out->is_iec61937_info_available) {
5112
5113 if (!audio_extn_passthru_is_passthrough_stream(out)) {
5114 out->is_iec61937_info_available = true;
5115 } else if (audio_extn_passthru_is_enabled()) {
5116 audio_extn_passthru_update_stream_configuration(adev, out, buffer, bytes);
Manish Dewangan37864bc2017-06-09 12:28:37 +05305117 out->is_iec61937_info_available = true;
Manish Dewangan671a4202017-08-18 17:30:46 +05305118
5119 if((out->format == AUDIO_FORMAT_DTS) ||
5120 (out->format == AUDIO_FORMAT_DTS_HD)) {
5121 ret = audio_extn_passthru_update_dts_stream_configuration(out,
5122 buffer, bytes);
5123 if (ret) {
5124 if (ret != -ENOSYS) {
5125 out->is_iec61937_info_available = false;
5126 ALOGD("iec61937 transmission info not yet updated retry");
5127 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305128 } else if (!out->standby) {
Manish Dewangan671a4202017-08-18 17:30:46 +05305129 /* if stream has started and after that there is
5130 * stream config change (iec transmission config)
5131 * then trigger select_device to update backend configuration.
5132 */
5133 out->stream_config_changed = true;
5134 pthread_mutex_lock(&adev->lock);
5135 select_devices(adev, out->usecase);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305136 if (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out)) {
Weiyin Jiang29c08a42019-04-30 17:11:10 +08005137 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305138 ret = -EINVAL;
5139 goto exit;
5140 }
Manish Dewangan671a4202017-08-18 17:30:46 +05305141 pthread_mutex_unlock(&adev->lock);
5142 out->stream_config_changed = false;
5143 out->is_iec61937_info_available = true;
5144 }
5145 }
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305146
Garmond Leung317cbf12017-09-13 16:20:50 -07005147 if ((channels < (int)audio_channel_count_from_out_mask(out->channel_mask)) &&
Satish Babu Patakokila715b1422017-08-22 14:33:21 +05305148 (out->compr_config.codec->compr_passthr == PASSTHROUGH) &&
5149 (out->is_iec61937_info_available == true)) {
5150 ALOGE("%s: ERROR: Unsupported channel config in passthrough mode", __func__);
5151 ret = -EINVAL;
5152 goto exit;
5153 }
Manish Dewangan37864bc2017-06-09 12:28:37 +05305154 }
5155 }
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305156
5157 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
Florian Pfister1a84f312018-07-19 14:38:18 +02005158 (audio_extn_a2dp_source_is_suspended())) {
Aalique Grahame22e49102018-12-18 14:23:57 -08005159 if (!(out->devices &
5160 (AUDIO_DEVICE_OUT_SPEAKER | AUDIO_DEVICE_OUT_SPEAKER_SAFE))) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305161 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05305162 ret = -EIO;
5163 goto exit;
5164 }
5165 }
5166 }
5167
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005168 if (out->standby) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005169 out->standby = false;
Eric Laurent150dbfe2013-02-27 14:31:02 -08005170 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005171 if (out->usecase == USECASE_COMPRESS_VOIP_CALL)
5172 ret = voice_extn_compress_voip_start_output_stream(out);
5173 else
5174 ret = start_output_stream(out);
Eric Laurent150dbfe2013-02-27 14:31:02 -08005175 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005176 /* ToDo: If use case is compress offload should return 0 */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005177 if (ret != 0) {
Ravi Kumar Alamanda59d296d2013-05-02 11:25:27 -07005178 out->standby = true;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005179 goto exit;
5180 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305181 out->started = 1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005182 if (last_known_cal_step != -1) {
5183 ALOGD("%s: retry previous failed cal level set", __func__);
5184 audio_hw_send_gain_dep_calibration(last_known_cal_step);
Preetam Singh Ranawatf4ae0222017-05-31 17:07:28 +05305185 last_known_cal_step = -1;
vivek mehtab72d08d2016-04-29 03:16:47 -07005186 }
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05305187
5188 if ((out->is_iec61937_info_available == true) &&
5189 (audio_extn_passthru_is_passthrough_stream(out))&&
5190 (!audio_extn_passthru_is_supported_backend_edid_cfg(adev, out))) {
5191 ret = -EINVAL;
5192 goto exit;
5193 }
Surendar Karkaf51b5842018-04-26 11:28:38 +05305194 if (out->set_dual_mono)
5195 audio_extn_send_dual_mono_mixing_coefficients(out);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005196 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005197
Ashish Jain81eb2a82015-05-13 10:52:34 +05305198 if (adev->is_channel_status_set == false && (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL)){
Alexy Josephb1379942016-01-29 15:49:38 -08005199 audio_utils_set_hdmi_channel_status(out, (void *)buffer, bytes);
Ashish Jain81eb2a82015-05-13 10:52:34 +05305200 adev->is_channel_status_set = true;
5201 }
5202
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05305203 if ((adev->use_old_pspd_mix_ctrl == true) &&
5204 (out->pspd_coeff_sent == false)) {
5205 /*
5206 * Need to resend pspd coefficients after stream started for
5207 * older kernel version as it does not save the coefficients
5208 * and also stream has to be started for coeff to apply.
5209 */
5210 usecase = get_usecase_from_list(adev, out->usecase);
5211 if (usecase != NULL) {
5212 audio_extn_set_custom_mtmx_params(adev, usecase, true);
5213 out->pspd_coeff_sent = true;
5214 }
5215 }
5216
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005217 if (is_offload_usecase(out->usecase)) {
Alexy Joseph01e54e62015-03-03 19:01:03 -08005218 ALOGVV("copl(%p): writing buffer (%zu bytes) to compress device", out, bytes);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005219 if (out->send_new_metadata) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005220 ALOGD("copl(%p):send new gapless metadata", out);
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005221 compress_set_gapless_metadata(out->compr, &out->gapless_mdata);
5222 out->send_new_metadata = 0;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305223 if (out->send_next_track_params && out->is_compr_metadata_avail) {
5224 ALOGD("copl(%p):send next track params in gapless", out);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08005225 // compress_set_next_track_param(out->compr, &(out->compr_config.codec->options));
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05305226 out->send_next_track_params = false;
5227 out->is_compr_metadata_avail = false;
5228 }
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005229 }
Dhananjay Kumarac341582017-02-23 23:42:25 +05305230 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305231 (out->convert_buffer) != NULL) {
Haynes Mathew George352f27b2013-07-26 00:00:15 -07005232
Ashish Jain83a6cc22016-06-28 14:34:17 +05305233 if ((bytes > out->hal_fragment_size)) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05305234 ALOGW("Error written bytes %zu > %d (fragment_size)",
Ashish Jain83a6cc22016-06-28 14:34:17 +05305235 bytes, out->hal_fragment_size);
Ashish Jainf1eaa582016-05-23 20:54:24 +05305236 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005237 ATRACE_END();
Ashish Jainf1eaa582016-05-23 20:54:24 +05305238 return -EINVAL;
5239 } else {
Ashish Jain83a6cc22016-06-28 14:34:17 +05305240 audio_format_t dst_format = out->hal_op_format;
5241 audio_format_t src_format = out->hal_ip_format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05305242
Dieter Luecking5d57def2018-09-07 14:23:37 +02005243 /* prevent division-by-zero */
5244 uint32_t bitwidth_src = format_to_bitwidth_table[src_format];
5245 uint32_t bitwidth_dst = format_to_bitwidth_table[dst_format];
5246 if ((bitwidth_src == 0) || (bitwidth_dst == 0)) {
5247 ALOGE("%s: Error bitwidth == 0", __func__);
Ramu Gottipati02809682018-12-19 16:46:12 +05305248 pthread_mutex_unlock(&out->lock);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005249 ATRACE_END();
5250 return -EINVAL;
5251 }
5252
Ashish Jainf1eaa582016-05-23 20:54:24 +05305253 uint32_t frames = bytes / format_to_bitwidth_table[src_format];
5254 uint32_t bytes_to_write = frames * format_to_bitwidth_table[dst_format];
5255
Ashish Jain83a6cc22016-06-28 14:34:17 +05305256 memcpy_by_audio_format(out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305257 dst_format,
5258 buffer,
5259 src_format,
5260 frames);
5261
Ashish Jain83a6cc22016-06-28 14:34:17 +05305262 ret = compress_write(out->compr, out->convert_buffer,
Ashish Jainf1eaa582016-05-23 20:54:24 +05305263 bytes_to_write);
5264
5265 /*Convert written bytes in audio flinger format*/
5266 if (ret > 0)
5267 ret = ((ret * format_to_bitwidth_table[out->format]) /
5268 format_to_bitwidth_table[dst_format]);
5269 }
5270 } else
5271 ret = compress_write(out->compr, buffer, bytes);
5272
Zhou Songc9672822017-08-16 16:01:39 +08005273 if ((ret < 0 || ret == (ssize_t)bytes) && !out->non_blocking)
5274 update_frames_written(out, bytes);
5275
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305276 if (ret < 0)
5277 ret = -errno;
Weiyin Jiangcc60dbb2018-08-21 13:12:03 +08005278 ALOGVV("%s: writing buffer (%zu bytes) to compress device returned %d", __func__, bytes, (int)ret);
Ashish Jainb26edfb2016-08-25 00:10:11 +05305279 /*msg to cb thread only if non blocking write is enabled*/
5280 if (ret >= 0 && ret < (ssize_t)bytes && out->non_blocking) {
Sidipotu Ashok55820562014-02-10 16:16:38 +05305281 ALOGD("No space available in compress driver, post msg to cb thread");
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005282 send_offload_cmd_l(out, OFFLOAD_CMD_WAIT_FOR_BUFFER);
Naresh Tanniru80659832014-06-04 18:17:56 +05305283 } else if (-ENETRESET == ret) {
5284 ALOGE("copl %s: received sound card offline state on compress write", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305285 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru80659832014-06-04 18:17:56 +05305286 pthread_mutex_unlock(&out->lock);
Dhananjay Kumar1248dd82017-07-28 21:22:16 +05305287 out_on_error(&out->stream.common);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005288 ATRACE_END();
Naresh Tanniru80659832014-06-04 18:17:56 +05305289 return ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005290 }
Ashish Jain5106d362016-05-11 19:23:33 +05305291
Dhanalakshmi Siddania6b76c72016-09-09 18:10:31 +05305292 /* Call compr start only when non-zero bytes of data is there to be rendered */
5293 if (!out->playback_started && ret > 0) {
5294 int status = compress_start(out->compr);
5295 if (status < 0) {
5296 ret = status;
5297 ALOGE("%s: compr start failed with err %d", __func__, errno);
5298 goto exit;
5299 }
Alexy Joseph7de344d2015-03-30 10:40:03 -07005300 audio_extn_dts_eagle_fade(adev, true, out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005301 out->playback_started = 1;
5302 out->offload_state = OFFLOAD_STATE_PLAYING;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005303
5304 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5305 popcount(out->channel_mask),
5306 out->playback_started);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005307 }
5308 pthread_mutex_unlock(&out->lock);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005309 ATRACE_END();
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005310 return ret;
5311 } else {
5312 if (out->pcm) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005313 size_t bytes_to_write = bytes;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005314 if (out->muted)
5315 memset((void *)buffer, 0, bytes);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005316 ALOGV("%s: frames=%zu, frame_size=%zu, bytes_to_write=%zu",
5317 __func__, frames, frame_size, bytes_to_write);
5318
Aalique Grahame22e49102018-12-18 14:23:57 -08005319 if (out->usecase == USECASE_INCALL_MUSIC_UPLINK ||
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07005320 out->usecase == USECASE_INCALL_MUSIC_UPLINK2 ||
5321 (out->usecase == USECASE_AUDIO_PLAYBACK_VOIP &&
5322 !audio_extn_utils_is_vendor_enhanced_fwk())) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005323 size_t channel_count = audio_channel_count_from_out_mask(out->channel_mask);
5324 int16_t *src = (int16_t *)buffer;
5325 int16_t *dst = (int16_t *)buffer;
5326
5327 LOG_ALWAYS_FATAL_IF(out->config.channels != 1 || channel_count != 2 ||
5328 out->format != AUDIO_FORMAT_PCM_16_BIT,
Aalique Grahame22e49102018-12-18 14:23:57 -08005329 "out_write called for %s use case with wrong properties",
5330 use_case_table[out->usecase]);
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005331
5332 /*
5333 * FIXME: this can be removed once audio flinger mixer supports
5334 * mono output
5335 */
5336
5337 /*
5338 * Code below goes over each frame in the buffer and adds both
5339 * L and R samples and then divides by 2 to convert to mono
5340 */
5341 for (size_t i = 0; i < frames ; i++, dst++, src += 2) {
5342 *dst = (int16_t)(((int32_t)src[0] + (int32_t)src[1]) >> 1);
5343 }
5344 bytes_to_write /= 2;
5345 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005346
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05305347 ALOGVV("%s: writing buffer (%zu bytes) to pcm device", __func__, bytes);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005348
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005349 long ns = 0;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005350
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005351 if (out->config.rate)
5352 ns = pcm_bytes_to_frames(out->pcm, bytes)*1000000000LL/
5353 out->config.rate;
5354
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005355 request_out_focus(out, ns);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005356 bool use_mmap = is_mmap_usecase(out->usecase) || out->realtime;
5357
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005358 if (use_mmap)
Arun Mirpuri7da752a2018-09-11 18:01:15 -07005359 ret = pcm_mmap_write(out->pcm, (void *)buffer, bytes_to_write);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005360 else if (out->hal_op_format != out->hal_ip_format &&
Ashish Jain83a6cc22016-06-28 14:34:17 +05305361 out->convert_buffer != NULL) {
5362
5363 memcpy_by_audio_format(out->convert_buffer,
5364 out->hal_op_format,
5365 buffer,
5366 out->hal_ip_format,
5367 out->config.period_size * out->config.channels);
5368
5369 ret = pcm_write(out->pcm, out->convert_buffer,
5370 (out->config.period_size *
5371 out->config.channels *
5372 format_to_bitwidth_table[out->hal_op_format]));
5373 } else {
Aditya Bavanarid4db8ee2017-05-29 21:08:03 +05305374 /*
5375 * To avoid underrun in DSP when the application is not pumping
5376 * data at required rate, check for the no. of bytes and ignore
5377 * pcm_write if it is less than actual buffer size.
5378 * It is a work around to a change in compress VOIP driver.
5379 */
5380 if ((out->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) &&
5381 bytes < (out->config.period_size * out->config.channels *
5382 audio_bytes_per_sample(out->format))) {
5383 size_t voip_buf_size =
5384 out->config.period_size * out->config.channels *
5385 audio_bytes_per_sample(out->format);
5386 ALOGE("%s:VOIP underrun: bytes received %zu, required:%zu\n",
5387 __func__, bytes, voip_buf_size);
5388 usleep(((uint64_t)voip_buf_size - bytes) *
5389 1000000 / audio_stream_out_frame_size(stream) /
5390 out_get_sample_rate(&out->stream.common));
5391 ret = 0;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08005392 } else {
5393 if (out->usecase == USECASE_AUDIO_PLAYBACK_WITH_HAPTICS)
5394 ret = split_and_write_audio_haptic_data(out, buffer, bytes);
5395 else
5396 ret = pcm_write(out->pcm, (void *)buffer, bytes_to_write);
5397 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05305398 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07005399
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005400 release_out_focus(out);
5401
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305402 if (ret < 0)
5403 ret = -errno;
Zhou Songc9672822017-08-16 16:01:39 +08005404 else if (ret > 0)
Ashish Jain83a6cc22016-06-28 14:34:17 +05305405 ret = -EINVAL;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005406 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005407 }
5408
5409exit:
Zhou Songc9672822017-08-16 16:01:39 +08005410 update_frames_written(out, bytes);
Naresh Tanniru4c630392014-05-12 01:05:52 +05305411 if (-ENETRESET == ret) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305412 out->card_status = CARD_STATUS_OFFLINE;
Naresh Tanniru4c630392014-05-12 01:05:52 +05305413 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005414 pthread_mutex_unlock(&out->lock);
5415
5416 if (ret != 0) {
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07005417 if (out->pcm)
Alexy Josephb1379942016-01-29 15:49:38 -08005418 ALOGE("%s: error %d, %s", __func__, (int)ret, pcm_get_error(out->pcm));
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305419 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305420 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305421 voice_extn_compress_voip_close_output_stream(&out->stream.common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05305422 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05305423 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05305424 out->standby = true;
5425 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305426 out_on_error(&out->stream.common);
Dieter Luecking5d57def2018-09-07 14:23:37 +02005427 if (!(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
5428 /* prevent division-by-zero */
5429 uint32_t stream_size = audio_stream_out_frame_size(stream);
5430 uint32_t srate = out_get_sample_rate(&out->stream.common);
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005431
Dieter Luecking5d57def2018-09-07 14:23:37 +02005432 if ((stream_size == 0) || (srate == 0)) {
5433 ALOGE("%s: stream_size= %d, srate = %d", __func__, stream_size, srate);
5434 ATRACE_END();
5435 return -EINVAL;
5436 }
5437 usleep((uint64_t)bytes * 1000000 / stream_size / srate);
5438 }
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005439 if (audio_extn_passthru_is_passthrough_stream(out)) {
Rajshekar Eashwarappa88834522018-04-02 17:20:15 +05305440 //ALOGE("%s: write error, ret = %zd", __func__, ret);
Haynes Mathew George380745d2017-10-04 15:27:45 -07005441 ATRACE_END();
Vidyakumar Athotaa9d3a5f2017-08-09 12:13:05 -07005442 return ret;
5443 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005444 }
Haynes Mathew George380745d2017-10-04 15:27:45 -07005445 ATRACE_END();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005446 return bytes;
5447}
5448
5449static int out_get_render_position(const struct audio_stream_out *stream,
5450 uint32_t *dsp_frames)
5451{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005452 struct stream_out *out = (struct stream_out *)stream;
Zhou Song32a556e2015-05-05 10:46:56 +08005453
5454 if (dsp_frames == NULL)
5455 return -EINVAL;
5456
5457 *dsp_frames = 0;
5458 if (is_offload_usecase(out->usecase)) {
Mingming Yin9e348b52014-11-19 16:18:55 -08005459 ssize_t ret = 0;
Ashish Jain5106d362016-05-11 19:23:33 +05305460
5461 /* Below piece of code is not guarded against any lock beacuse audioFliner serializes
5462 * this operation and adev_close_output_stream(where out gets reset).
5463 */
Dhananjay Kumarac341582017-02-23 23:42:25 +05305464 if (!out->non_blocking && !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005465 *dsp_frames = get_actual_pcm_frames_rendered(out, NULL);
Ashish Jain5106d362016-05-11 19:23:33 +05305466 ALOGVV("dsp_frames %d sampleRate %d",(int)*dsp_frames,out->sample_rate);
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005467 adjust_frames_for_device_delay(out, dsp_frames);
Ashish Jain5106d362016-05-11 19:23:33 +05305468 return 0;
5469 }
5470
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005471 lock_output_stream(out);
Ashish Jain5106d362016-05-11 19:23:33 +05305472 if (out->compr != NULL && out->non_blocking) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305473 ret = compress_get_tstamp(out->compr, (unsigned long *)dsp_frames,
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005474 &out->sample_rate);
Dhanalakshmi Siddani37ca1d62014-08-20 12:28:34 +05305475 if (ret < 0)
5476 ret = -errno;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005477 ALOGVV("%s rendered frames %d sample_rate %d",
Ashish Jain5106d362016-05-11 19:23:33 +05305478 __func__, *dsp_frames, out->sample_rate);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005479 }
Naresh Tanniru80659832014-06-04 18:17:56 +05305480 if (-ENETRESET == ret) {
5481 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305482 out->card_status = CARD_STATUS_OFFLINE;
5483 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305484 } else if(ret < 0) {
5485 ALOGE(" ERROR: Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305486 ret = -EINVAL;
5487 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Preetam Singh Ranawat2d0e4632015-02-02 12:40:59 +05305488 /*
5489 * Handle corner case where compress session is closed during SSR
5490 * and timestamp is queried
5491 */
5492 ALOGE(" ERROR: sound card not active, return error");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305493 ret = -EINVAL;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305494 } else if (out->prev_card_status_offline) {
5495 ALOGE("ERROR: previously sound card was offline,return error");
5496 ret = -EINVAL;
Naresh Tanniru80659832014-06-04 18:17:56 +05305497 } else {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305498 ret = 0;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005499 adjust_frames_for_device_delay(out, dsp_frames);
Naresh Tanniru80659832014-06-04 18:17:56 +05305500 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305501 pthread_mutex_unlock(&out->lock);
5502 return ret;
Zhou Song32a556e2015-05-05 10:46:56 +08005503 } else if (audio_is_linear_pcm(out->format)) {
5504 *dsp_frames = out->written;
Haynes Mathew Georgeb0f5dc32017-10-06 18:35:12 -07005505 adjust_frames_for_device_delay(out, dsp_frames);
Zhou Song32a556e2015-05-05 10:46:56 +08005506 return 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005507 } else
5508 return -EINVAL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005509}
5510
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005511static int out_add_audio_effect(const struct audio_stream *stream __unused,
5512 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005513{
5514 return 0;
5515}
5516
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005517static int out_remove_audio_effect(const struct audio_stream *stream __unused,
5518 effect_handle_t effect __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005519{
5520 return 0;
5521}
5522
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005523static int out_get_next_write_timestamp(const struct audio_stream_out *stream __unused,
5524 int64_t *timestamp __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005525{
Satya Krishna Pindiprolib6655542017-07-03 19:38:19 +05305526 return -ENOSYS;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005527}
5528
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005529static int out_get_presentation_position(const struct audio_stream_out *stream,
5530 uint64_t *frames, struct timespec *timestamp)
5531{
5532 struct stream_out *out = (struct stream_out *)stream;
pavance65c2fe2017-10-18 17:52:01 +05305533 int ret = -ENODATA;
Eric Laurent949a0892013-09-20 09:20:13 -07005534 unsigned long dsp_frames;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005535
Ashish Jain5106d362016-05-11 19:23:33 +05305536 /* below piece of code is not guarded against any lock because audioFliner serializes
5537 * this operation and adev_close_output_stream( where out gets reset).
5538 */
5539 if (is_offload_usecase(out->usecase) && !out->non_blocking &&
Dhananjay Kumarac341582017-02-23 23:42:25 +05305540 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Zhou Song48453a02018-01-10 17:50:59 +08005541 *frames = get_actual_pcm_frames_rendered(out, timestamp);
Ashish Jain5106d362016-05-11 19:23:33 +05305542 ALOGVV("frames %lld playedat %lld",(long long int)*frames,
5543 timestamp->tv_sec * 1000000LL + timestamp->tv_nsec / 1000);
5544 return 0;
5545 }
5546
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005547 lock_output_stream(out);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005548
Ashish Jain5106d362016-05-11 19:23:33 +05305549 if (is_offload_usecase(out->usecase) && out->compr != NULL && out->non_blocking) {
5550 ret = compress_get_tstamp(out->compr, &dsp_frames,
5551 &out->sample_rate);
yidongh0515e042017-07-06 15:00:34 +08005552 // Adjustment accounts for A2dp encoder latency with offload usecases
5553 // Note: Encoder latency is returned in ms.
5554 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5555 unsigned long offset =
5556 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5557 dsp_frames = (dsp_frames > offset) ? (dsp_frames - offset) : 0;
5558 }
Ashish Jain5106d362016-05-11 19:23:33 +05305559 ALOGVV("%s rendered frames %ld sample_rate %d",
5560 __func__, dsp_frames, out->sample_rate);
5561 *frames = dsp_frames;
5562 if (ret < 0)
5563 ret = -errno;
5564 if (-ENETRESET == ret) {
5565 ALOGE(" ERROR: sound card not active Unable to get time stamp from compress driver");
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305566 out->card_status = CARD_STATUS_OFFLINE;
Ashish Jain5106d362016-05-11 19:23:33 +05305567 ret = -EINVAL;
5568 } else
5569 ret = 0;
5570 /* this is the best we can do */
5571 clock_gettime(CLOCK_MONOTONIC, timestamp);
Eric Laurent949a0892013-09-20 09:20:13 -07005572 } else {
5573 if (out->pcm) {
Weiyin Jiangd4633762018-03-16 12:05:03 +08005574 unsigned int avail;
5575 if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
5576 size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
5577 int64_t signed_frames = out->written - kernel_buffer_size + avail;
5578 // This adjustment accounts for buffering after app processor.
5579 // It is based on estimated DSP latency per use case, rather than exact.
Haynes Mathew George7ff216f2013-09-11 19:51:41 -07005580 signed_frames -=
Weiyin Jiangd4633762018-03-16 12:05:03 +08005581 (platform_render_latency(out->usecase) * out->sample_rate / 1000000LL);
Aniket Kumar Lataff613152017-07-18 18:19:21 -07005582
Weiyin Jiangd4633762018-03-16 12:05:03 +08005583 // Adjustment accounts for A2dp encoder latency with non offload usecases
5584 // Note: Encoder latency is returned in ms, while platform_render_latency in us.
5585 if (AUDIO_DEVICE_OUT_ALL_A2DP & out->devices) {
5586 signed_frames -=
5587 (audio_extn_a2dp_get_encoder_latency() * out->sample_rate / 1000);
5588 }
5589
5590 // It would be unusual for this value to be negative, but check just in case ...
5591 if (signed_frames >= 0) {
5592 *frames = signed_frames;
5593 ret = 0;
5594 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005595 }
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305596 } else if (out->card_status == CARD_STATUS_OFFLINE) {
Ashish Jainbbce4322016-02-16 13:25:27 +05305597 *frames = out->written;
5598 clock_gettime(CLOCK_MONOTONIC, timestamp);
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05305599 if (is_offload_usecase(out->usecase))
5600 ret = -EINVAL;
5601 else
5602 ret = 0;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005603 }
5604 }
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005605 pthread_mutex_unlock(&out->lock);
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07005606 return ret;
5607}
5608
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005609static int out_set_callback(struct audio_stream_out *stream,
5610 stream_callback_t callback, void *cookie)
5611{
5612 struct stream_out *out = (struct stream_out *)stream;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005613 int ret;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005614
5615 ALOGV("%s", __func__);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005616 lock_output_stream(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08005617 out->client_callback = callback;
5618 out->client_cookie = cookie;
5619 if (out->adsp_hdlr_stream_handle) {
5620 ret = audio_extn_adsp_hdlr_stream_set_callback(
5621 out->adsp_hdlr_stream_handle,
5622 callback,
5623 cookie);
5624 if (ret)
5625 ALOGW("%s:adsp hdlr callback registration failed %d",
5626 __func__, ret);
5627 }
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005628 pthread_mutex_unlock(&out->lock);
5629 return 0;
5630}
5631
5632static int out_pause(struct audio_stream_out* stream)
5633{
5634 struct stream_out *out = (struct stream_out *)stream;
5635 int status = -ENOSYS;
5636 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005637 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005638 ALOGD("copl(%p):pause compress driver", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005639 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005640 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PLAYING) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305641 if (out->card_status != CARD_STATUS_OFFLINE)
Naresh Tanniru80659832014-06-04 18:17:56 +05305642 status = compress_pause(out->compr);
5643
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005644 out->offload_state = OFFLOAD_STATE_PAUSED;
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005645
Mingming Yin21854652016-04-13 11:54:02 -07005646 if (audio_extn_passthru_is_active()) {
5647 ALOGV("offload use case, pause passthru");
5648 audio_extn_passthru_on_pause(out);
5649 }
5650
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305651 audio_extn_dts_eagle_fade(adev, false, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005652 audio_extn_dts_notify_playback_state(out->usecase, 0,
5653 out->sample_rate, popcount(out->channel_mask),
5654 0);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005655 }
5656 pthread_mutex_unlock(&out->lock);
5657 }
5658 return status;
5659}
5660
5661static int out_resume(struct audio_stream_out* stream)
5662{
5663 struct stream_out *out = (struct stream_out *)stream;
5664 int status = -ENOSYS;
5665 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005666 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005667 ALOGD("copl(%p):resume compress driver", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005668 status = 0;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005669 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005670 if (out->compr != NULL && out->offload_state == OFFLOAD_STATE_PAUSED) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05305671 if (out->card_status != CARD_STATUS_OFFLINE) {
Naresh Tanniru80659832014-06-04 18:17:56 +05305672 status = compress_resume(out->compr);
Mingming Yin21854652016-04-13 11:54:02 -07005673 }
5674 if (!status) {
5675 out->offload_state = OFFLOAD_STATE_PLAYING;
5676 }
Dhanalakshmi Siddani79415e72015-03-23 11:54:47 +05305677 audio_extn_dts_eagle_fade(adev, true, out);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08005678 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
5679 popcount(out->channel_mask), 1);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005680 }
5681 pthread_mutex_unlock(&out->lock);
5682 }
5683 return status;
5684}
5685
5686static int out_drain(struct audio_stream_out* stream, audio_drain_type_t type )
5687{
5688 struct stream_out *out = (struct stream_out *)stream;
5689 int status = -ENOSYS;
5690 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005691 if (is_offload_usecase(out->usecase)) {
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005692 lock_output_stream(out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005693 if (type == AUDIO_DRAIN_EARLY_NOTIFY)
5694 status = send_offload_cmd_l(out, OFFLOAD_CMD_PARTIAL_DRAIN);
5695 else
5696 status = send_offload_cmd_l(out, OFFLOAD_CMD_DRAIN);
5697 pthread_mutex_unlock(&out->lock);
5698 }
5699 return status;
5700}
5701
5702static int out_flush(struct audio_stream_out* stream)
5703{
5704 struct stream_out *out = (struct stream_out *)stream;
5705 ALOGV("%s", __func__);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07005706 if (is_offload_usecase(out->usecase)) {
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005707 ALOGD("copl(%p):calling compress flush", out);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005708 lock_output_stream(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005709 if (out->offload_state == OFFLOAD_STATE_PAUSED) {
5710 stop_compressed_output_l(out);
Haynes Mathew Georgeafe54d82016-09-21 14:39:19 -07005711 } else {
5712 ALOGW("%s called in invalid state %d", __func__, out->offload_state);
5713 }
Weiyin Jiang547e4152017-09-14 17:24:18 +08005714 out->written = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005715 pthread_mutex_unlock(&out->lock);
Apoorv Raghuvanshi44bd9172014-05-28 14:50:07 -07005716 ALOGD("copl(%p):out of compress flush", out);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07005717 return 0;
5718 }
5719 return -ENOSYS;
5720}
5721
Haynes Mathew George16081042017-05-31 17:16:49 -07005722static int out_stop(const struct audio_stream_out* stream)
5723{
5724 struct stream_out *out = (struct stream_out *)stream;
5725 struct audio_device *adev = out->dev;
5726 int ret = -ENOSYS;
5727
5728 ALOGV("%s", __func__);
5729 pthread_mutex_lock(&adev->lock);
5730 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5731 out->playback_started && out->pcm != NULL) {
5732 pcm_stop(out->pcm);
5733 ret = stop_output_stream(out);
5734 out->playback_started = false;
5735 }
5736 pthread_mutex_unlock(&adev->lock);
5737 return ret;
5738}
5739
5740static int out_start(const struct audio_stream_out* stream)
5741{
5742 struct stream_out *out = (struct stream_out *)stream;
5743 struct audio_device *adev = out->dev;
5744 int ret = -ENOSYS;
5745
5746 ALOGV("%s", __func__);
5747 pthread_mutex_lock(&adev->lock);
5748 if (out->usecase == USECASE_AUDIO_PLAYBACK_MMAP && !out->standby &&
5749 !out->playback_started && out->pcm != NULL) {
5750 ret = start_output_stream(out);
5751 if (ret == 0) {
5752 out->playback_started = true;
5753 }
5754 }
5755 pthread_mutex_unlock(&adev->lock);
5756 return ret;
5757}
5758
5759/*
5760 * Modify config->period_count based on min_size_frames
5761 */
5762static void adjust_mmap_period_count(struct pcm_config *config, int32_t min_size_frames)
5763{
5764 int periodCountRequested = (min_size_frames + config->period_size - 1)
5765 / config->period_size;
5766 int periodCount = MMAP_PERIOD_COUNT_MIN;
5767
5768 ALOGV("%s original config.period_size = %d config.period_count = %d",
5769 __func__, config->period_size, config->period_count);
5770
5771 while (periodCount < periodCountRequested && (periodCount * 2) < MMAP_PERIOD_COUNT_MAX) {
5772 periodCount *= 2;
5773 }
5774 config->period_count = periodCount;
5775
5776 ALOGV("%s requested config.period_count = %d", __func__, config->period_count);
5777}
5778
Phil Burkfe17efd2019-03-25 10:23:35 -07005779// Read offset for the positional timestamp from a persistent vendor property.
5780// This is to workaround apparent inaccuracies in the timing information that
5781// is used by the AAudio timing model. The inaccuracies can cause glitches.
5782static int64_t get_mmap_out_time_offset() {
5783 const int32_t kDefaultOffsetMicros = 0;
5784 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08005785 "persist.vendor.audio.out_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burkfe17efd2019-03-25 10:23:35 -07005786 ALOGI("mmap_time_offset_micros = %d for output", mmap_time_offset_micros);
5787 return mmap_time_offset_micros * (int64_t)1000;
5788}
5789
Haynes Mathew George16081042017-05-31 17:16:49 -07005790static int out_create_mmap_buffer(const struct audio_stream_out *stream,
5791 int32_t min_size_frames,
5792 struct audio_mmap_buffer_info *info)
5793{
5794 struct stream_out *out = (struct stream_out *)stream;
5795 struct audio_device *adev = out->dev;
5796 int ret = 0;
Aalique Grahame1f123102017-10-12 10:38:32 -07005797 unsigned int offset1 = 0;
5798 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07005799 const char *step = "";
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005800 uint32_t mmap_size;
Arun Mirpuri5d170872019-03-26 13:21:31 -07005801 uint32_t buffer_size;
Haynes Mathew George16081042017-05-31 17:16:49 -07005802
Arun Mirpuri5d170872019-03-26 13:21:31 -07005803 ALOGD("%s", __func__);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305804 lock_output_stream(out);
Haynes Mathew George16081042017-05-31 17:16:49 -07005805 pthread_mutex_lock(&adev->lock);
5806
Sharad Sanglec6f32552018-05-04 16:15:38 +05305807 if (CARD_STATUS_OFFLINE == out->card_status ||
5808 CARD_STATUS_OFFLINE == adev->card_status) {
5809 ALOGW("out->card_status or adev->card_status offline, try again");
5810 ret = -EIO;
5811 goto exit;
5812 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005813 if (info == NULL || min_size_frames == 0) {
5814 ALOGE("%s: info = %p, min_size_frames = %d", __func__, info, min_size_frames);
5815 ret = -EINVAL;
5816 goto exit;
5817 }
5818 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP || !out->standby) {
5819 ALOGE("%s: usecase = %d, standby = %d", __func__, out->usecase, out->standby);
5820 ret = -ENOSYS;
5821 goto exit;
5822 }
5823 out->pcm_device_id = platform_get_pcm_device_id(out->usecase, PCM_PLAYBACK);
5824 if (out->pcm_device_id < 0) {
5825 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
5826 __func__, out->pcm_device_id, out->usecase);
5827 ret = -EINVAL;
5828 goto exit;
5829 }
5830
5831 adjust_mmap_period_count(&out->config, min_size_frames);
5832
Arun Mirpuri5d170872019-03-26 13:21:31 -07005833 ALOGD("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005834 __func__, adev->snd_card, out->pcm_device_id, out->config.channels);
5835 out->pcm = pcm_open(adev->snd_card, out->pcm_device_id,
5836 (PCM_OUT | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &out->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05305837 if (errno == ENETRESET && !pcm_is_ready(out->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05305838 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
5839 out->card_status = CARD_STATUS_OFFLINE;
5840 adev->card_status = CARD_STATUS_OFFLINE;
5841 ret = -EIO;
5842 goto exit;
5843 }
5844
Haynes Mathew George16081042017-05-31 17:16:49 -07005845 if (out->pcm == NULL || !pcm_is_ready(out->pcm)) {
5846 step = "open";
5847 ret = -ENODEV;
5848 goto exit;
5849 }
5850 ret = pcm_mmap_begin(out->pcm, &info->shared_memory_address, &offset1, &frames1);
5851 if (ret < 0) {
5852 step = "begin";
5853 goto exit;
5854 }
5855 info->buffer_size_frames = pcm_get_buffer_size(out->pcm);
Arun Mirpuri5d170872019-03-26 13:21:31 -07005856 buffer_size = pcm_frames_to_bytes(out->pcm, info->buffer_size_frames);
Haynes Mathew George16081042017-05-31 17:16:49 -07005857 info->burst_size_frames = out->config.period_size;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005858 ret = platform_get_mmap_data_fd(adev->platform,
5859 out->pcm_device_id, 0 /*playback*/,
5860 &info->shared_memory_fd,
5861 &mmap_size);
5862 if (ret < 0) {
Arun Mirpuri5d170872019-03-26 13:21:31 -07005863 // Fall back to non exclusive mode
5864 info->shared_memory_fd = pcm_get_poll_fd(out->pcm);
5865 } else {
5866 if (mmap_size < buffer_size) {
5867 step = "mmap";
5868 goto exit;
5869 }
5870 // FIXME: indicate exclusive mode support by returning a negative buffer size
5871 info->buffer_size_frames *= -1;
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005872 }
Haynes Mathew George16081042017-05-31 17:16:49 -07005873 memset(info->shared_memory_address, 0, pcm_frames_to_bytes(out->pcm,
Haynes Mathew Georgeef514882017-05-01 17:46:23 -07005874 info->buffer_size_frames));
Haynes Mathew George16081042017-05-31 17:16:49 -07005875
5876 ret = pcm_mmap_commit(out->pcm, 0, MMAP_PERIOD_SIZE);
5877 if (ret < 0) {
5878 step = "commit";
5879 goto exit;
5880 }
5881
Phil Burkfe17efd2019-03-25 10:23:35 -07005882 out->mmap_time_offset_nanos = get_mmap_out_time_offset();
5883
Haynes Mathew George16081042017-05-31 17:16:49 -07005884 out->standby = false;
5885 ret = 0;
5886
Arun Mirpuri5d170872019-03-26 13:21:31 -07005887 ALOGD("%s: got mmap buffer address %p info->buffer_size_frames %d",
Haynes Mathew George16081042017-05-31 17:16:49 -07005888 __func__, info->shared_memory_address, info->buffer_size_frames);
5889
5890exit:
5891 if (ret != 0) {
5892 if (out->pcm == NULL) {
5893 ALOGE("%s: %s - %d", __func__, step, ret);
5894 } else {
5895 ALOGE("%s: %s %s", __func__, step, pcm_get_error(out->pcm));
5896 pcm_close(out->pcm);
5897 out->pcm = NULL;
5898 }
5899 }
5900 pthread_mutex_unlock(&adev->lock);
Sharad Sanglec6f32552018-05-04 16:15:38 +05305901 pthread_mutex_unlock(&out->lock);
Haynes Mathew George16081042017-05-31 17:16:49 -07005902 return ret;
5903}
5904
5905static int out_get_mmap_position(const struct audio_stream_out *stream,
5906 struct audio_mmap_position *position)
5907{
5908 struct stream_out *out = (struct stream_out *)stream;
5909 ALOGVV("%s", __func__);
5910 if (position == NULL) {
5911 return -EINVAL;
5912 }
5913 if (out->usecase != USECASE_AUDIO_PLAYBACK_MMAP) {
Haynes Mathew George4ab3ba92017-12-11 14:49:43 -08005914 ALOGE("%s: called on %s", __func__, use_case_table[out->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005915 return -ENOSYS;
5916 }
5917 if (out->pcm == NULL) {
5918 return -ENOSYS;
5919 }
5920
5921 struct timespec ts = { 0, 0 };
5922 int ret = pcm_mmap_get_hw_ptr(out->pcm, (unsigned int *)&position->position_frames, &ts);
5923 if (ret < 0) {
5924 ALOGE("%s: %s", __func__, pcm_get_error(out->pcm));
5925 return ret;
5926 }
Phil Burkfe17efd2019-03-25 10:23:35 -07005927 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
5928 + out->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07005929 return 0;
5930}
5931
5932
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005933/** audio_stream_in implementation **/
5934static uint32_t in_get_sample_rate(const struct audio_stream *stream)
5935{
5936 struct stream_in *in = (struct stream_in *)stream;
5937
5938 return in->config.rate;
5939}
5940
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005941static int in_set_sample_rate(struct audio_stream *stream __unused,
5942 uint32_t rate __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005943{
5944 return -ENOSYS;
5945}
5946
5947static size_t in_get_buffer_size(const struct audio_stream *stream)
5948{
5949 struct stream_in *in = (struct stream_in *)stream;
5950
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005951 if(in->usecase == USECASE_COMPRESS_VOIP_CALL)
5952 return voice_extn_compress_voip_in_get_buffer_size(in);
Vikram Panduranga93f080e2017-06-07 18:16:14 -07005953 else if(in->usecase == USECASE_AUDIO_RECORD_VOIP)
5954 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 -07005955 else if(audio_extn_compr_cap_usecase_supported(in->usecase))
5956 return audio_extn_compr_cap_get_buffer_size(in->config.format);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05305957 else if(audio_extn_cin_attached_usecase(in->usecase))
5958 return audio_extn_cin_get_buffer_size(in);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005959
Haynes Mathew George5beddd42016-06-27 18:33:40 -07005960 return in->config.period_size * in->af_period_multiplier *
5961 audio_stream_in_frame_size((const struct audio_stream_in *)stream);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005962}
5963
5964static uint32_t in_get_channels(const struct audio_stream *stream)
5965{
5966 struct stream_in *in = (struct stream_in *)stream;
5967
5968 return in->channel_mask;
5969}
5970
5971static audio_format_t in_get_format(const struct audio_stream *stream)
5972{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08005973 struct stream_in *in = (struct stream_in *)stream;
5974
5975 return in->format;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005976}
5977
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07005978static int in_set_format(struct audio_stream *stream __unused,
5979 audio_format_t format __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08005980{
5981 return -ENOSYS;
5982}
5983
5984static int in_standby(struct audio_stream *stream)
5985{
5986 struct stream_in *in = (struct stream_in *)stream;
5987 struct audio_device *adev = in->dev;
5988 int status = 0;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305989 ALOGD("%s: enter: stream (%p) usecase(%d: %s)", __func__,
5990 stream, in->usecase, use_case_table[in->usecase]);
Haynes Mathew George16081042017-05-31 17:16:49 -07005991 bool do_stop = true;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05305992
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07005993 lock_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005994 if (!in->standby && in->is_st_session) {
5995 ALOGD("%s: sound trigger pcm stop lab", __func__);
5996 audio_extn_sound_trigger_stop_lab(in);
Quinn Malef6050362019-01-30 15:55:40 -08005997 adev->num_va_sessions--;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07005998 in->standby = 1;
5999 }
6000
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006001 if (!in->standby) {
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006002 if (adev->adm_deregister_stream)
6003 adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
6004
Ravi Kumar Alamanda8bba9e92013-11-11 21:09:07 -08006005 pthread_mutex_lock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006006 in->standby = true;
Zhou Songa8895042016-07-05 17:54:22 +08006007 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
kunleizbecba2d2017-09-07 13:37:16 +08006008 do_stop = false;
Zhou Songa8895042016-07-05 17:54:22 +08006009 voice_extn_compress_voip_close_input_stream(stream);
6010 ALOGD("VOIP input entered standby");
Haynes Mathew George16081042017-05-31 17:16:49 -07006011 } else if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6012 do_stop = in->capture_started;
6013 in->capture_started = false;
Zhou Songa8895042016-07-05 17:54:22 +08006014 } else {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306015 if (audio_extn_cin_attached_usecase(in->usecase))
6016 audio_extn_cin_stop_input_stream(in);
kunleizbecba2d2017-09-07 13:37:16 +08006017 }
6018
Arun Mirpuri5d170872019-03-26 13:21:31 -07006019 if (in->pcm) {
6020 ATRACE_BEGIN("pcm_in_close");
6021 pcm_close(in->pcm);
6022 ATRACE_END();
6023 in->pcm = NULL;
6024 }
6025
6026 if(do_stop) {
Aalique Grahame22e49102018-12-18 14:23:57 -08006027 adev->enable_voicerx = false;
6028 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
Zhou Songa8895042016-07-05 17:54:22 +08006029 status = stop_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006030 }
Quinn Malef6050362019-01-30 15:55:40 -08006031
6032 if (in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6033 adev->num_va_sessions--;
6034
Eric Laurent150dbfe2013-02-27 14:31:02 -08006035 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006036 }
6037 pthread_mutex_unlock(&in->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07006038 ALOGV("%s: exit: status(%d)", __func__, status);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006039 return status;
6040}
6041
Aalique Grahame22e49102018-12-18 14:23:57 -08006042static int in_dump(const struct audio_stream *stream,
6043 int fd)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006044{
Aalique Grahame22e49102018-12-18 14:23:57 -08006045 struct stream_in *in = (struct stream_in *)stream;
6046
6047 // We try to get the lock for consistency,
6048 // but it isn't necessary for these variables.
6049 // If we're not in standby, we may be blocked on a read.
6050 const bool locked = (pthread_mutex_trylock(&in->lock) == 0);
6051 dprintf(fd, " Standby: %s\n", in->standby ? "yes" : "no");
6052 dprintf(fd, " Frames read: %lld\n", (long long)in->frames_read);
6053 dprintf(fd, " Frames muted: %lld\n", (long long)in->frames_muted);
6054
6055 if (locked) {
6056 pthread_mutex_unlock(&in->lock);
6057 }
6058
6059 // dump error info
6060 (void)error_log_dump(
6061 in->error_log, fd, " " /* prefix */, 0 /* lines */, 0 /* limit_ns */);
6062
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006063 return 0;
6064}
6065
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306066static void in_snd_mon_cb(void * stream, struct str_parms * parms)
6067{
6068 if (!stream || !parms)
6069 return;
6070
6071 struct stream_in *in = (struct stream_in *)stream;
6072 struct audio_device *adev = in->dev;
6073
6074 card_status_t status;
6075 int card;
6076 if (parse_snd_card_status(parms, &card, &status) < 0)
6077 return;
6078
6079 pthread_mutex_lock(&adev->lock);
6080 bool valid_cb = (card == adev->snd_card);
6081 pthread_mutex_unlock(&adev->lock);
6082
6083 if (!valid_cb)
6084 return;
6085
6086 lock_input_stream(in);
6087 if (in->card_status != status)
6088 in->card_status = status;
6089 pthread_mutex_unlock(&in->lock);
6090
6091 ALOGW("in_snd_mon_cb for card %d usecase %s, status %s", card,
6092 use_case_table[in->usecase],
6093 status == CARD_STATUS_OFFLINE ? "offline" : "online");
6094
6095 // a better solution would be to report error back to AF and let
6096 // it put the stream to standby
6097 if (status == CARD_STATUS_OFFLINE)
6098 in_standby(&in->stream.common);
6099
6100 return;
6101}
6102
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006103static int in_set_parameters(struct audio_stream *stream, const char *kvpairs)
6104{
6105 struct stream_in *in = (struct stream_in *)stream;
6106 struct audio_device *adev = in->dev;
6107 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006108 char value[32];
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006109 int ret = 0, val = 0, err;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006110
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306111 ALOGD("%s: enter: kvpairs=%s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006112 parms = str_parms_create_str(kvpairs);
6113
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306114 if (!parms)
6115 goto error;
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006116 lock_input_stream(in);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006117 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006118
6119 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_INPUT_SOURCE, value, sizeof(value));
6120 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006121 val = atoi(value);
6122 /* no audio source uses val == 0 */
6123 if ((in->source != val) && (val != 0)) {
6124 in->source = val;
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006125 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) &&
6126 (in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
6127 (voice_extn_compress_voip_is_format_supported(in->format)) &&
Shiv Maliyappanahallie66aba22016-01-27 16:08:57 -08006128 (in->config.rate == 8000 || in->config.rate == 16000 ||
6129 in->config.rate == 32000 || in->config.rate == 48000 ) &&
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07006130 (audio_channel_count_from_in_mask(in->channel_mask) == 1)) {
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006131 err = voice_extn_compress_voip_open_input_stream(in);
6132 if (err != 0) {
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006133 ALOGE("%s: Compress voip input cannot be opened, error:%d",
Narsinga Rao Chella7d5a3e82014-02-04 16:23:52 -08006134 __func__, err);
Narsinga Rao Chella2a99dea2014-01-24 15:33:23 -08006135 }
6136 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006137 }
6138 }
6139
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08006140 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
6141 if (err >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006142 val = atoi(value);
Kevin Rocardfce19002017-08-07 19:21:36 -07006143 if (((int)in->device != val) && (val != 0) && audio_is_input_device(val) ) {
6144
6145 // Workaround: If routing to an non existing usb device, fail gracefully
6146 // The routing request will otherwise block during 10 second
6147 int card;
6148 if (audio_is_usb_in_device(val) &&
6149 (card = get_alive_usb_card(parms)) >= 0) {
6150
6151 ALOGW("in_set_parameters() ignoring rerouting to non existing USB card %d", card);
6152 ret = -ENOSYS;
6153 } else {
6154
6155 in->device = val;
6156 /* If recording is in progress, change the tx device to new device */
6157 if (!in->standby && !in->is_st_session) {
6158 ALOGV("update input routing change");
6159 // inform adm before actual routing to prevent glitches.
6160 if (adev->adm_on_routing_change) {
Haynes Mathew George822b5492016-07-01 16:57:24 -07006161 adev->adm_on_routing_change(adev->adm_data,
6162 in->capture_handle);
Kevin Rocardfce19002017-08-07 19:21:36 -07006163 ret = select_devices(adev, in->usecase);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006164 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6165 adev->adm_routing_changed = true;
Kevin Rocardfce19002017-08-07 19:21:36 -07006166 }
6167 }
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006168 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006169 }
6170 }
6171
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05306172 err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_PROFILE, value, sizeof(value));
6173 if (err >= 0) {
6174 strlcpy(in->profile, value, sizeof(in->profile));
6175 ALOGV("updating stream profile with value '%s'", in->profile);
6176 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
6177 &adev->streams_input_cfg_list,
6178 in->device, in->flags, in->format,
6179 in->sample_rate, in->bit_width,
6180 in->profile, &in->app_type_cfg);
6181 }
6182
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006183 pthread_mutex_unlock(&adev->lock);
Eric Laurent150dbfe2013-02-27 14:31:02 -08006184 pthread_mutex_unlock(&in->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006185
6186 str_parms_destroy(parms);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05306187error:
Eric Laurent994a6932013-07-17 11:51:42 -07006188 ALOGV("%s: exit: status(%d)", __func__, ret);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006189 return ret;
6190}
6191
6192static char* in_get_parameters(const struct audio_stream *stream,
6193 const char *keys)
6194{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006195 struct stream_in *in = (struct stream_in *)stream;
6196 struct str_parms *query = str_parms_create_str(keys);
6197 char *str;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006198 struct str_parms *reply = str_parms_create();
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006199
6200 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08006201 if (reply) {
6202 str_parms_destroy(reply);
6203 }
6204 if (query) {
6205 str_parms_destroy(query);
6206 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07006207 ALOGE("in_get_parameters: failed to create query or reply");
6208 return NULL;
6209 }
6210
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006211 ALOGV("%s: enter: keys - %s %s ", __func__, use_case_table[in->usecase], keys);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006212
6213 voice_extn_in_get_parameters(in, query, reply);
6214
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006215 stream_get_parameter_channels(query, reply,
6216 &in->supported_channel_masks[0]);
6217 stream_get_parameter_formats(query, reply,
6218 &in->supported_formats[0]);
6219 stream_get_parameter_rates(query, reply,
6220 &in->supported_sample_rates[0]);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08006221 str = str_parms_to_str(reply);
6222 str_parms_destroy(query);
6223 str_parms_destroy(reply);
6224
6225 ALOGV("%s: exit: returns - %s", __func__, str);
6226 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006227}
6228
Aalique Grahame22e49102018-12-18 14:23:57 -08006229static int in_set_gain(struct audio_stream_in *stream,
6230 float gain)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006231{
Aalique Grahame22e49102018-12-18 14:23:57 -08006232 struct stream_in *in = (struct stream_in *)stream;
6233 char mixer_ctl_name[128];
6234 struct mixer_ctl *ctl;
6235 int ctl_value;
6236
6237 ALOGV("%s: gain %f", __func__, gain);
6238
6239 if (stream == NULL)
6240 return -EINVAL;
6241
6242 /* in_set_gain() only used to silence MMAP capture for now */
6243 if (in->usecase != USECASE_AUDIO_RECORD_MMAP)
6244 return -ENOSYS;
6245
6246 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "Capture %d Volume", in->pcm_device_id);
6247
6248 ctl = mixer_get_ctl_by_name(in->dev->mixer, mixer_ctl_name);
6249 if (!ctl) {
6250 ALOGW("%s: Could not get ctl for mixer cmd - %s",
6251 __func__, mixer_ctl_name);
6252 return -ENOSYS;
6253 }
6254
6255 if (gain < RECORD_GAIN_MIN)
6256 gain = RECORD_GAIN_MIN;
6257 else if (gain > RECORD_GAIN_MAX)
6258 gain = RECORD_GAIN_MAX;
6259 ctl_value = (int)(RECORD_VOLUME_CTL_MAX * gain);
6260
6261 mixer_ctl_set_value(ctl, 0, ctl_value);
6262
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006263 return 0;
6264}
6265
6266static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
6267 size_t bytes)
6268{
6269 struct stream_in *in = (struct stream_in *)stream;
Pallavid7c7a272018-01-16 11:22:55 +05306270
6271 if (in == NULL) {
6272 ALOGE("%s: stream_in ptr is NULL", __func__);
6273 return -EINVAL;
6274 }
6275
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006276 struct audio_device *adev = in->dev;
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05306277 int ret = -1;
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306278 size_t bytes_read = 0, frame_size = 0;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006279
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006280 lock_input_stream(in);
Naresh Tanniru4c630392014-05-12 01:05:52 +05306281
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006282 if (in->is_st_session) {
6283 ALOGVV(" %s: reading on st session bytes=%zu", __func__, bytes);
6284 /* Read from sound trigger HAL */
6285 audio_extn_sound_trigger_read(in, buffer, bytes);
Quinn Malef6050362019-01-30 15:55:40 -08006286 if (in->standby) {
6287 adev->num_va_sessions++;
6288 in->standby = 0;
6289 }
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006290 pthread_mutex_unlock(&in->lock);
6291 return bytes;
6292 }
6293
Haynes Mathew George16081042017-05-31 17:16:49 -07006294 if (in->usecase == USECASE_AUDIO_RECORD_MMAP) {
6295 ret = -ENOSYS;
6296 goto exit;
6297 }
6298
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006299 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY &&
6300 !in->standby && adev->adm_routing_changed) {
6301 ret = -ENOSYS;
6302 goto exit;
6303 }
6304
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006305 if (in->standby) {
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006306 pthread_mutex_lock(&adev->lock);
6307 if (in->usecase == USECASE_COMPRESS_VOIP_CALL)
6308 ret = voice_extn_compress_voip_start_input_stream(in);
6309 else
6310 ret = start_input_stream(in);
Quinn Malef6050362019-01-30 15:55:40 -08006311 if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
6312 adev->num_va_sessions++;
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006313 pthread_mutex_unlock(&adev->lock);
6314 if (ret != 0) {
6315 goto exit;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006316 }
6317 in->standby = 0;
6318 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006319
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006320 // what's the duration requested by the client?
6321 long ns = 0;
6322
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306323 if (in->pcm && in->config.rate)
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006324 ns = pcm_bytes_to_frames(in->pcm, bytes)*1000000000LL/
6325 in->config.rate;
6326
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006327 ret = request_in_focus(in, ns);
6328 if (ret != 0)
6329 goto exit;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006330 bool use_mmap = is_mmap_usecase(in->usecase) || in->realtime;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006331
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306332 if (audio_extn_cin_attached_usecase(in->usecase)) {
6333 ret = audio_extn_cin_read(in, buffer, bytes, &bytes_read);
6334 } else if (in->pcm) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306335 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006336 ret = audio_extn_ssr_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306337 } else if (audio_extn_compr_cap_usecase_supported(in->usecase)) {
Mingming Yine62d7842013-10-25 16:26:03 -07006338 ret = audio_extn_compr_cap_read(in, buffer, bytes);
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006339 } else if (use_mmap) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07006340 ret = pcm_mmap_read(in->pcm, buffer, bytes);
Garmond Leunge2433c32017-09-28 21:51:22 -07006341 } else if (audio_extn_ffv_get_stream() == in) {
6342 ret = audio_extn_ffv_read(stream, buffer, bytes);
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306343 } else {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07006344 ret = pcm_read(in->pcm, buffer, bytes);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306345 /* data from DSP comes in 24_8 format, convert it to 8_24 */
6346 if (!ret && bytes > 0 && (in->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
6347 if (audio_extn_utils_convert_format_24_8_to_8_24(buffer, bytes)
6348 != bytes) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306349 ret = -EINVAL;
6350 goto exit;
6351 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306352 } else if (ret < 0) {
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05306353 ret = -errno;
6354 }
6355 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306356 /* bytes read is always set to bytes for non compress usecases */
6357 bytes_read = bytes;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006358 }
6359
Haynes Mathew George5beddd42016-06-27 18:33:40 -07006360 release_in_focus(in);
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07006361
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006362 /*
Quinn Malef6050362019-01-30 15:55:40 -08006363 * Instead of writing zeroes here, we could trust the hardware to always
6364 * provide zeroes when muted. This is also muted with voice recognition
6365 * usecases so that other clients do not have access to voice recognition
6366 * data.
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006367 */
Quinn Malef6050362019-01-30 15:55:40 -08006368 if ((ret == 0 && voice_get_mic_mute(adev) &&
6369 !voice_is_in_call_rec_stream(in) &&
6370 in->usecase != USECASE_AUDIO_RECORD_AFE_PROXY) ||
6371 (adev->num_va_sessions &&
6372 in->source != AUDIO_SOURCE_VOICE_RECOGNITION &&
6373 property_get_bool("persist.vendor.audio.va_concurrency_mute_enabled",
6374 false)))
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006375 memset(buffer, 0, bytes);
6376
6377exit:
Dhananjay Kumar97b81e32019-05-15 21:00:21 +05306378 frame_size = audio_stream_in_frame_size(stream);
6379 if (frame_size > 0)
6380 in->frames_read += bytes_read/frame_size;
6381
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07006382 if (-ENETRESET == ret)
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05306383 in->card_status = CARD_STATUS_OFFLINE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006384 pthread_mutex_unlock(&in->lock);
6385
6386 if (ret != 0) {
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306387 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306388 pthread_mutex_lock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306389 voice_extn_compress_voip_close_input_stream(&in->stream.common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05306390 pthread_mutex_unlock(&adev->lock);
Venkata Narendra Kumar Guttabc9c9ca2014-06-25 20:38:03 +05306391 in->standby = true;
6392 }
Sharad Sangled17c9122017-03-20 15:58:52 +05306393 if (!audio_extn_cin_attached_usecase(in->usecase)) {
6394 bytes_read = bytes;
6395 memset(buffer, 0, bytes);
6396 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006397 in_standby(&in->stream.common);
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07006398 if (in->usecase == USECASE_AUDIO_RECORD_LOW_LATENCY)
6399 adev->adm_routing_changed = false;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07006400 ALOGV("%s: read failed status %d- sleeping for buffer duration", __func__, ret);
Ashish Jainbbce4322016-02-16 13:25:27 +05306401 usleep((uint64_t)bytes * 1000000 / audio_stream_in_frame_size(stream) /
Naresh Tanniru4c630392014-05-12 01:05:52 +05306402 in_get_sample_rate(&in->stream.common));
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006403 }
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05306404 return bytes_read;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006405}
6406
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07006407static uint32_t in_get_input_frames_lost(struct audio_stream_in *stream __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006408{
6409 return 0;
6410}
6411
Aalique Grahame22e49102018-12-18 14:23:57 -08006412static int in_get_capture_position(const struct audio_stream_in *stream,
6413 int64_t *frames, int64_t *time)
6414{
6415 if (stream == NULL || frames == NULL || time == NULL) {
6416 return -EINVAL;
6417 }
6418 struct stream_in *in = (struct stream_in *)stream;
6419 int ret = -ENOSYS;
6420
6421 lock_input_stream(in);
6422 // note: ST sessions do not close the alsa pcm driver synchronously
6423 // on standby. Therefore, we may return an error even though the
6424 // pcm stream is still opened.
6425 if (in->standby) {
6426 ALOGE_IF(in->pcm != NULL && !in->is_st_session,
6427 "%s stream in standby but pcm not NULL for non ST session", __func__);
6428 goto exit;
6429 }
6430 if (in->pcm) {
6431 struct timespec timestamp;
6432 unsigned int avail;
6433 if (pcm_get_htimestamp(in->pcm, &avail, &timestamp) == 0) {
6434 *frames = in->frames_read + avail;
6435 *time = timestamp.tv_sec * 1000000000LL + timestamp.tv_nsec;
6436 ret = 0;
6437 }
6438 }
6439exit:
6440 pthread_mutex_unlock(&in->lock);
6441 return ret;
6442}
6443
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006444static int add_remove_audio_effect(const struct audio_stream *stream,
6445 effect_handle_t effect,
6446 bool enable)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006447{
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006448 struct stream_in *in = (struct stream_in *)stream;
6449 int status = 0;
6450 effect_descriptor_t desc;
6451
6452 status = (*effect)->get_descriptor(effect, &desc);
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006453 ALOGV("%s: status %d in->standby %d enable:%d", __func__, status, in->standby, enable);
6454
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006455 if (status != 0)
6456 return status;
6457
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006458 lock_input_stream(in);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006459 pthread_mutex_lock(&in->dev->lock);
kunleizd96526c2018-04-09 11:12:32 +08006460 if ((in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
Aalique Grahame22e49102018-12-18 14:23:57 -08006461 in->source == AUDIO_SOURCE_VOICE_RECOGNITION ||
kunleizd96526c2018-04-09 11:12:32 +08006462 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006463 in->enable_aec != enable &&
6464 (memcmp(&desc.type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0)) {
6465 in->enable_aec = enable;
Aalique Grahame22e49102018-12-18 14:23:57 -08006466 if (!enable)
6467 platform_set_echo_reference(in->dev, enable, AUDIO_DEVICE_NONE);
6468 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6469 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
6470 in->dev->enable_voicerx = enable;
6471 struct audio_usecase *usecase;
6472 struct listnode *node;
6473 list_for_each(node, &in->dev->usecase_list) {
6474 usecase = node_to_item(node, struct audio_usecase, list);
6475 if (usecase->type == PCM_PLAYBACK)
6476 select_devices(in->dev, usecase->id);
6477 }
6478 }
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006479 if (!in->standby) {
6480 if (enable_disable_effect(in->dev, EFFECT_AEC, enable) == ENOSYS)
6481 select_devices(in->dev, in->usecase);
6482 }
6483
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006484 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006485 if (in->enable_ns != enable &&
6486 (memcmp(&desc.type, FX_IID_NS, sizeof(effect_uuid_t)) == 0)) {
6487 in->enable_ns = enable;
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006488 if (!in->standby) {
kunleizd96526c2018-04-09 11:12:32 +08006489 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION ||
6490 in->dev->mode == AUDIO_MODE_IN_COMMUNICATION) {
Vikram Pandurangadf59cae2017-08-03 18:04:55 -07006491 if (enable_disable_effect(in->dev, EFFECT_NS, enable) == ENOSYS)
6492 select_devices(in->dev, in->usecase);
6493 } else
6494 select_devices(in->dev, in->usecase);
6495 }
Ravi Kumar Alamanda198185e2013-11-07 15:42:19 -08006496 }
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006497 pthread_mutex_unlock(&in->dev->lock);
6498 pthread_mutex_unlock(&in->lock);
6499
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006500 return 0;
6501}
6502
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006503static int in_add_audio_effect(const struct audio_stream *stream,
6504 effect_handle_t effect)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006505{
Eric Laurent994a6932013-07-17 11:51:42 -07006506 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006507 return add_remove_audio_effect(stream, effect, true);
6508}
6509
6510static int in_remove_audio_effect(const struct audio_stream *stream,
6511 effect_handle_t effect)
6512{
Eric Laurent994a6932013-07-17 11:51:42 -07006513 ALOGV("%s: effect %p", __func__, effect);
Ravi Kumar Alamandaf70ffb42013-04-16 15:55:53 -07006514 return add_remove_audio_effect(stream, effect, false);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006515}
6516
Derek Chenf939fb72018-11-13 13:34:41 -08006517streams_input_ctxt_t *in_get_stream(struct audio_device *dev,
6518 audio_io_handle_t input)
6519{
6520 struct listnode *node;
6521
6522 list_for_each(node, &dev->active_inputs_list) {
6523 streams_input_ctxt_t *in_ctxt = node_to_item(node,
6524 streams_input_ctxt_t,
6525 list);
6526 if (in_ctxt->input->capture_handle == input) {
6527 return in_ctxt;
6528 }
6529 }
6530 return NULL;
6531}
6532
6533streams_output_ctxt_t *out_get_stream(struct audio_device *dev,
6534 audio_io_handle_t output)
6535{
6536 struct listnode *node;
6537
6538 list_for_each(node, &dev->active_outputs_list) {
6539 streams_output_ctxt_t *out_ctxt = node_to_item(node,
6540 streams_output_ctxt_t,
6541 list);
6542 if (out_ctxt->output->handle == output) {
6543 return out_ctxt;
6544 }
6545 }
6546 return NULL;
6547}
6548
Haynes Mathew George16081042017-05-31 17:16:49 -07006549static int in_stop(const struct audio_stream_in* stream)
6550{
6551 struct stream_in *in = (struct stream_in *)stream;
6552 struct audio_device *adev = in->dev;
6553
6554 int ret = -ENOSYS;
6555 ALOGV("%s", __func__);
6556 pthread_mutex_lock(&adev->lock);
6557 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6558 in->capture_started && in->pcm != NULL) {
6559 pcm_stop(in->pcm);
6560 ret = stop_input_stream(in);
6561 in->capture_started = false;
6562 }
6563 pthread_mutex_unlock(&adev->lock);
6564 return ret;
6565}
6566
6567static int in_start(const struct audio_stream_in* stream)
6568{
6569 struct stream_in *in = (struct stream_in *)stream;
6570 struct audio_device *adev = in->dev;
6571 int ret = -ENOSYS;
6572
6573 ALOGV("%s in %p", __func__, in);
6574 pthread_mutex_lock(&adev->lock);
6575 if (in->usecase == USECASE_AUDIO_RECORD_MMAP && !in->standby &&
6576 !in->capture_started && in->pcm != NULL) {
6577 if (!in->capture_started) {
6578 ret = start_input_stream(in);
6579 if (ret == 0) {
6580 in->capture_started = true;
6581 }
6582 }
6583 }
6584 pthread_mutex_unlock(&adev->lock);
6585 return ret;
6586}
6587
Phil Burke0a86d12019-02-16 22:28:11 -08006588// Read offset for the positional timestamp from a persistent vendor property.
6589// This is to workaround apparent inaccuracies in the timing information that
6590// is used by the AAudio timing model. The inaccuracies can cause glitches.
6591static int64_t in_get_mmap_time_offset() {
6592 const int32_t kDefaultOffsetMicros = 0;
6593 int32_t mmap_time_offset_micros = property_get_int32(
Weiyin Jiangbd68b4d2019-05-17 16:29:50 +08006594 "persist.vendor.audio.in_mmap_delay_micros", kDefaultOffsetMicros);
Phil Burke0a86d12019-02-16 22:28:11 -08006595 ALOGI("mmap_time_offset_micros = %d for input", mmap_time_offset_micros);
6596 return mmap_time_offset_micros * (int64_t)1000;
6597}
6598
Haynes Mathew George16081042017-05-31 17:16:49 -07006599static int in_create_mmap_buffer(const struct audio_stream_in *stream,
6600 int32_t min_size_frames,
6601 struct audio_mmap_buffer_info *info)
6602{
6603 struct stream_in *in = (struct stream_in *)stream;
6604 struct audio_device *adev = in->dev;
6605 int ret = 0;
Aniket Kumar Lataf9f246e2017-09-15 15:20:16 -07006606 unsigned int offset1 = 0;
6607 unsigned int frames1 = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006608 const char *step = "";
Arun Mirpuri5d170872019-03-26 13:21:31 -07006609 uint32_t mmap_size = 0;
6610 uint32_t buffer_size = 0;
Haynes Mathew George16081042017-05-31 17:16:49 -07006611
6612 pthread_mutex_lock(&adev->lock);
6613 ALOGV("%s in %p", __func__, in);
6614
Sharad Sanglec6f32552018-05-04 16:15:38 +05306615 if (CARD_STATUS_OFFLINE == in->card_status||
6616 CARD_STATUS_OFFLINE == adev->card_status) {
6617 ALOGW("in->card_status or adev->card_status offline, try again");
6618 ret = -EIO;
6619 goto exit;
6620 }
6621
Haynes Mathew George16081042017-05-31 17:16:49 -07006622 if (info == NULL || min_size_frames == 0) {
6623 ALOGE("%s invalid argument info %p min_size_frames %d", __func__, info, min_size_frames);
6624 ret = -EINVAL;
6625 goto exit;
6626 }
6627 if (in->usecase != USECASE_AUDIO_RECORD_MMAP || !in->standby) {
6628 ALOGE("%s: usecase = %d, standby = %d", __func__, in->usecase, in->standby);
6629 ALOGV("%s in %p", __func__, in);
6630 ret = -ENOSYS;
6631 goto exit;
6632 }
6633 in->pcm_device_id = platform_get_pcm_device_id(in->usecase, PCM_CAPTURE);
6634 if (in->pcm_device_id < 0) {
6635 ALOGE("%s: Invalid PCM device id(%d) for the usecase(%d)",
6636 __func__, in->pcm_device_id, in->usecase);
6637 ret = -EINVAL;
6638 goto exit;
6639 }
6640
6641 adjust_mmap_period_count(&in->config, min_size_frames);
6642
6643 ALOGV("%s: Opening PCM device card_id(%d) device_id(%d), channels %d",
6644 __func__, adev->snd_card, in->pcm_device_id, in->config.channels);
6645 in->pcm = pcm_open(adev->snd_card, in->pcm_device_id,
6646 (PCM_IN | PCM_MMAP | PCM_NOIRQ | PCM_MONOTONIC), &in->config);
Satish Babu Patakokila54ce83d2018-07-06 18:00:37 +05306647 if (errno == ENETRESET && !pcm_is_ready(in->pcm)) {
Sharad Sanglec6f32552018-05-04 16:15:38 +05306648 ALOGE("%s: pcm_open failed errno:%d\n", __func__, errno);
6649 in->card_status = CARD_STATUS_OFFLINE;
6650 adev->card_status = CARD_STATUS_OFFLINE;
6651 ret = -EIO;
6652 goto exit;
6653 }
6654
Haynes Mathew George16081042017-05-31 17:16:49 -07006655 if (in->pcm == NULL || !pcm_is_ready(in->pcm)) {
6656 step = "open";
6657 ret = -ENODEV;
6658 goto exit;
6659 }
6660
6661 ret = pcm_mmap_begin(in->pcm, &info->shared_memory_address, &offset1, &frames1);
6662 if (ret < 0) {
6663 step = "begin";
6664 goto exit;
6665 }
Haynes Mathew George16081042017-05-31 17:16:49 -07006666
Arun Mirpuri5d170872019-03-26 13:21:31 -07006667 info->buffer_size_frames = pcm_get_buffer_size(in->pcm);
6668 buffer_size = pcm_frames_to_bytes(in->pcm, info->buffer_size_frames);
6669 info->burst_size_frames = in->config.period_size;
6670 ret = platform_get_mmap_data_fd(adev->platform,
6671 in->pcm_device_id, 1 /*capture*/,
6672 &info->shared_memory_fd,
6673 &mmap_size);
6674 if (ret < 0) {
6675 // Fall back to non exclusive mode
6676 info->shared_memory_fd = pcm_get_poll_fd(in->pcm);
6677 } else {
6678 if (mmap_size < buffer_size) {
6679 step = "mmap";
6680 goto exit;
6681 }
6682 // FIXME: indicate exclusive mode support by returning a negative buffer size
6683 info->buffer_size_frames *= -1;
6684 }
6685
6686 memset(info->shared_memory_address, 0, buffer_size);
Haynes Mathew George16081042017-05-31 17:16:49 -07006687
6688 ret = pcm_mmap_commit(in->pcm, 0, MMAP_PERIOD_SIZE);
6689 if (ret < 0) {
6690 step = "commit";
6691 goto exit;
6692 }
6693
Phil Burke0a86d12019-02-16 22:28:11 -08006694 in->mmap_time_offset_nanos = in_get_mmap_time_offset();
6695
Haynes Mathew George16081042017-05-31 17:16:49 -07006696 in->standby = false;
6697 ret = 0;
6698
6699 ALOGV("%s: got mmap buffer address %p info->buffer_size_frames %d",
6700 __func__, info->shared_memory_address, info->buffer_size_frames);
6701
6702exit:
6703 if (ret != 0) {
6704 if (in->pcm == NULL) {
6705 ALOGE("%s: %s - %d", __func__, step, ret);
6706 } else {
6707 ALOGE("%s: %s %s", __func__, step, pcm_get_error(in->pcm));
6708 pcm_close(in->pcm);
6709 in->pcm = NULL;
6710 }
6711 }
6712 pthread_mutex_unlock(&adev->lock);
6713 return ret;
6714}
6715
6716static int in_get_mmap_position(const struct audio_stream_in *stream,
6717 struct audio_mmap_position *position)
6718{
6719 struct stream_in *in = (struct stream_in *)stream;
6720 ALOGVV("%s", __func__);
6721 if (position == NULL) {
6722 return -EINVAL;
6723 }
6724 if (in->usecase != USECASE_AUDIO_RECORD_MMAP) {
6725 return -ENOSYS;
6726 }
6727 if (in->pcm == NULL) {
6728 return -ENOSYS;
6729 }
6730 struct timespec ts = { 0, 0 };
6731 int ret = pcm_mmap_get_hw_ptr(in->pcm, (unsigned int *)&position->position_frames, &ts);
6732 if (ret < 0) {
6733 ALOGE("%s: %s", __func__, pcm_get_error(in->pcm));
6734 return ret;
6735 }
Phil Burke0a86d12019-02-16 22:28:11 -08006736 position->time_nanoseconds = ts.tv_sec*1000000000LL + ts.tv_nsec
6737 + in->mmap_time_offset_nanos;
Haynes Mathew George16081042017-05-31 17:16:49 -07006738 return 0;
6739}
6740
Naresh Tannirudcb47c52018-06-25 16:23:32 +05306741static int in_get_active_microphones(const struct audio_stream_in *stream,
6742 struct audio_microphone_characteristic_t *mic_array,
6743 size_t *mic_count) {
6744 struct stream_in *in = (struct stream_in *)stream;
6745 struct audio_device *adev = in->dev;
6746 ALOGVV("%s", __func__);
6747
6748 lock_input_stream(in);
6749 pthread_mutex_lock(&adev->lock);
6750 int ret = platform_get_active_microphones(adev->platform,
6751 audio_channel_count_from_in_mask(in->channel_mask),
6752 in->usecase, mic_array, mic_count);
6753 pthread_mutex_unlock(&adev->lock);
6754 pthread_mutex_unlock(&in->lock);
6755
6756 return ret;
6757}
6758
6759static int adev_get_microphones(const struct audio_hw_device *dev,
6760 struct audio_microphone_characteristic_t *mic_array,
6761 size_t *mic_count) {
6762 struct audio_device *adev = (struct audio_device *)dev;
6763 ALOGVV("%s", __func__);
6764
6765 pthread_mutex_lock(&adev->lock);
6766 int ret = platform_get_microphones(adev->platform, mic_array, mic_count);
6767 pthread_mutex_unlock(&adev->lock);
6768
6769 return ret;
6770}
juyuchendb308c22019-01-21 11:57:17 -07006771
6772static void in_update_sink_metadata(struct audio_stream_in *stream,
6773 const struct sink_metadata *sink_metadata) {
6774
6775 if (stream == NULL
6776 || sink_metadata == NULL
6777 || sink_metadata->tracks == NULL) {
6778 return;
6779 }
6780
6781 int error = 0;
6782 struct stream_in *in = (struct stream_in *)stream;
6783 struct audio_device *adev = in->dev;
6784 audio_devices_t device = AUDIO_DEVICE_NONE;
6785
6786 if (sink_metadata->track_count != 0)
6787 device = sink_metadata->tracks->dest_device;
6788
6789 lock_input_stream(in);
6790 pthread_mutex_lock(&adev->lock);
6791 ALOGV("%s: in->usecase: %d, device: %x", __func__, in->usecase, device);
6792
6793 if (in->usecase == USECASE_AUDIO_RECORD_AFE_PROXY
6794 && device != AUDIO_DEVICE_NONE
6795 && adev->voice_tx_output != NULL) {
6796 /* Use the rx device from afe-proxy record to route voice call because
6797 there is no routing if tx device is on primary hal and rx device
6798 is on other hal during voice call. */
6799 adev->voice_tx_output->devices = device;
6800
6801 if (!voice_is_call_state_active(adev)) {
6802 if (adev->mode == AUDIO_MODE_IN_CALL) {
6803 adev->current_call_output = adev->voice_tx_output;
6804 error = voice_start_call(adev);
6805 if (error != 0)
6806 ALOGE("%s: start voice call failed %d", __func__, error);
6807 }
6808 } else {
6809 adev->current_call_output = adev->voice_tx_output;
6810 voice_update_devices_for_all_voice_usecases(adev);
6811 }
6812 }
6813
6814 pthread_mutex_unlock(&adev->lock);
6815 pthread_mutex_unlock(&in->lock);
6816}
6817
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05306818int adev_open_output_stream(struct audio_hw_device *dev,
Haynes Mathew George16081042017-05-31 17:16:49 -07006819 audio_io_handle_t handle,
6820 audio_devices_t devices,
6821 audio_output_flags_t flags,
6822 struct audio_config *config,
6823 struct audio_stream_out **stream_out,
Derek Chenf6318be2017-06-12 17:16:24 -04006824 const char *address)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006825{
6826 struct audio_device *adev = (struct audio_device *)dev;
6827 struct stream_out *out;
Gangadhar Sb0210342019-02-22 17:39:41 +05306828 int ret = 0, ip_hdlr_stream = 0, ip_hdlr_dev = 0;
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07006829 audio_format_t format;
Ben Rombergerd771a7c2017-02-22 18:05:17 -08006830 struct adsp_hdlr_stream_cfg hdlr_stream_cfg;
Manish Dewangan21a850a2017-08-14 12:03:55 +05306831 bool is_direct_passthough = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006832 bool is_hdmi = devices & AUDIO_DEVICE_OUT_AUX_DIGITAL;
6833 bool is_usb_dev = audio_is_usb_out_device(devices) &&
6834 (devices != AUDIO_DEVICE_OUT_USB_ACCESSORY);
6835 bool direct_dev = is_hdmi || is_usb_dev;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006836 bool use_db_as_primary =
vivek mehtaae1018c2019-05-09 12:19:57 -07006837 property_get_bool("vendor.audio.feature.deepbuffer_as_primary.enable",
6838 false);
Vignesh Kulothungana6927272019-02-20 15:17:07 -08006839 bool force_haptic_path =
6840 property_get_bool("vendor.audio.test_haptic", false);
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07006841 bool is_voip_rx = flags & AUDIO_OUTPUT_FLAG_VOIP_RX;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006842
kunleizdff872d2018-08-20 14:40:33 +08006843 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08006844 is_usb_dev = false;
6845 devices = AUDIO_DEVICE_OUT_SPEAKER;
6846 ALOGW("%s: ignore set device to non existing USB card, use output device(%#x)",
6847 __func__, devices);
6848 }
6849
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006850 *stream_out = NULL;
Naresh Tanniru80659832014-06-04 18:17:56 +05306851
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006852 out = (struct stream_out *)calloc(1, sizeof(struct stream_out));
6853
Mingming Yin3a941d42016-02-17 18:08:05 -08006854 ALOGD("%s: enter: format(%#x) sample_rate(%d) channel_mask(%#x) devices(%#x) flags(%#x)\
Derek Chenf6318be2017-06-12 17:16:24 -04006855 stream_handle(%p) address(%s)", __func__, config->format, config->sample_rate, config->channel_mask,
6856 devices, flags, &out->stream, address);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05306857
6858
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08006859 if (!out) {
6860 return -ENOMEM;
6861 }
6862
Haynes Mathew George204045b2015-02-25 20:32:03 -08006863 pthread_mutex_init(&out->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07006864 pthread_mutex_init(&out->pre_lock, (const pthread_mutexattr_t *) NULL);
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306865 pthread_mutex_init(&out->compr_mute_lock, (const pthread_mutexattr_t *) NULL);
Zhou Song48453a02018-01-10 17:50:59 +08006866 pthread_mutex_init(&out->position_query_lock, (const pthread_mutexattr_t *) NULL);
Haynes Mathew George204045b2015-02-25 20:32:03 -08006867 pthread_cond_init(&out->cond, (const pthread_condattr_t *) NULL);
6868
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006869 if (devices == AUDIO_DEVICE_NONE)
6870 devices = AUDIO_DEVICE_OUT_SPEAKER;
6871
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006872 out->flags = flags;
6873 out->devices = devices;
Haynes Mathew George47cd4cb2013-07-19 11:58:50 -07006874 out->dev = adev;
Aalique Grahame65780b52017-09-27 14:59:56 -07006875 out->hal_op_format = out->hal_ip_format = format = out->format = config->format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07006876 out->sample_rate = config->sample_rate;
Sachin Mohan Gadag3d09acd2017-06-19 12:43:44 +05306877 out->channel_mask = config->channel_mask;
Ramjee Singh5857aeb2017-08-03 19:18:50 +05306878 if (out->channel_mask == AUDIO_CHANNEL_NONE)
6879 out->supported_channel_masks[0] = AUDIO_CHANNEL_OUT_STEREO;
6880 else
6881 out->supported_channel_masks[0] = out->channel_mask;
Eric Laurentc4aef752013-09-12 17:45:53 -07006882 out->handle = handle;
Mingming Yin3ee55c62014-08-04 14:23:35 -07006883 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Alexy Josephaa54c872014-12-03 02:46:47 -08006884 out->non_blocking = 0;
Ashish Jain83a6cc22016-06-28 14:34:17 +05306885 out->convert_buffer = NULL;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05306886 out->started = 0;
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05306887 out->a2dp_compress_mute = false;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08006888 out->hal_output_suspend_supported = 0;
6889 out->dynamic_pm_qos_config_supported = 0;
Surendar Karkaf51b5842018-04-26 11:28:38 +05306890 out->set_dual_mono = false;
Manisha Agarwal7b3e3772019-02-20 14:33:45 +05306891 out->prev_card_status_offline = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05306892 out->pspd_coeff_sent = false;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08006893
Nikhil Laturkar26b690b2017-07-25 11:06:14 +05306894 if ((flags & AUDIO_OUTPUT_FLAG_BD) &&
Satish Babu Patakokila37e7c482018-02-02 11:50:06 +05306895 (property_get_bool("vendor.audio.matrix.limiter.enable", false)))
Ben Romberger6c4d3812017-06-13 17:46:45 -07006896 platform_set_device_params(out, DEVICE_PARAM_LIMITER_ID, 1);
6897
Aalique Grahame22e49102018-12-18 14:23:57 -08006898 if (direct_dev &&
6899 (audio_is_linear_pcm(out->format) ||
6900 config->format == AUDIO_FORMAT_DEFAULT) &&
6901 out->flags == AUDIO_OUTPUT_FLAG_NONE) {
6902 audio_format_t req_format = config->format;
6903 audio_channel_mask_t req_channel_mask = config->channel_mask;
6904 uint32_t req_sample_rate = config->sample_rate;
6905
6906 pthread_mutex_lock(&adev->lock);
6907 if (is_hdmi) {
6908 ALOGV("AUDIO_DEVICE_OUT_AUX_DIGITAL and DIRECT|OFFLOAD, check hdmi caps");
6909 ret = read_hdmi_sink_caps(out);
6910 if (config->sample_rate == 0)
6911 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
6912 if (config->channel_mask == AUDIO_CHANNEL_NONE)
6913 config->channel_mask = AUDIO_CHANNEL_OUT_5POINT1;
6914 if (config->format == AUDIO_FORMAT_DEFAULT)
6915 config->format = AUDIO_FORMAT_PCM_16_BIT;
6916 } else if (is_usb_dev) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006917 ret = read_usb_sup_params_and_compare(true /*is_playback*/,
6918 &config->format,
6919 &out->supported_formats[0],
6920 MAX_SUPPORTED_FORMATS,
6921 &config->channel_mask,
6922 &out->supported_channel_masks[0],
6923 MAX_SUPPORTED_CHANNEL_MASKS,
6924 &config->sample_rate,
6925 &out->supported_sample_rates[0],
6926 MAX_SUPPORTED_SAMPLE_RATES);
6927 ALOGV("plugged dev USB ret %d", ret);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006928 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006929
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006930 pthread_mutex_unlock(&adev->lock);
6931 if (ret != 0) {
Mingming Yin3a941d42016-02-17 18:08:05 -08006932 if (ret == -ENOSYS) {
6933 /* ignore and go with default */
6934 ret = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08006935 }
6936 // For MMAP NO IRQ, allow conversions in ADSP
6937 else if (is_hdmi || (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0)
6938 goto error_open;
6939 else {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07006940 ALOGE("error reading direct dev sink caps");
Mingming Yin3a941d42016-02-17 18:08:05 -08006941 goto error_open;
6942 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006943
6944 if (req_sample_rate != 0 && config->sample_rate != req_sample_rate)
6945 config->sample_rate = req_sample_rate;
6946 if (req_channel_mask != AUDIO_CHANNEL_NONE && config->channel_mask != req_channel_mask)
6947 config->channel_mask = req_channel_mask;
6948 if (req_format != AUDIO_FORMAT_DEFAULT && config->format != req_format)
6949 config->format = req_format;
Mingming Yin3a941d42016-02-17 18:08:05 -08006950 }
Aalique Grahame22e49102018-12-18 14:23:57 -08006951
6952 out->sample_rate = config->sample_rate;
6953 out->channel_mask = config->channel_mask;
6954 out->format = config->format;
6955 if (is_hdmi) {
6956 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6957 out->config = pcm_config_hdmi_multi;
6958 } else if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
6959 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
6960 out->config = pcm_config_mmap_playback;
6961 out->stream.start = out_start;
6962 out->stream.stop = out_stop;
6963 out->stream.create_mmap_buffer = out_create_mmap_buffer;
6964 out->stream.get_mmap_position = out_get_mmap_position;
6965 } else {
6966 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
6967 out->config = pcm_config_hifi;
6968 }
6969
6970 out->config.rate = out->sample_rate;
6971 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
6972 if (is_hdmi) {
6973 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
6974 audio_bytes_per_sample(out->format));
6975 }
6976 out->config.format = pcm_format_from_audio_format(out->format);
Mingming Yin3a941d42016-02-17 18:08:05 -08006977 }
6978
Derek Chenf6318be2017-06-12 17:16:24 -04006979 /* validate bus device address */
6980 if (out->devices & AUDIO_DEVICE_OUT_BUS) {
6981 /* extract car audio stream index */
6982 out->car_audio_stream =
6983 audio_extn_auto_hal_get_car_audio_stream_from_address(address);
6984 if (out->car_audio_stream < 0) {
6985 ALOGE("%s: invalid car audio stream %x",
6986 __func__, out->car_audio_stream);
6987 ret = -EINVAL;
6988 goto error_open;
6989 }
6990 /* save car audio stream and address for bus device */
6991 strlcpy(out->address, address, AUDIO_DEVICE_MAX_ADDRESS_LEN);
6992 ALOGV("%s: address %s, car_audio_stream %x",
6993 __func__, out->address, out->car_audio_stream);
6994 }
6995
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006996 /* Check for VOIP usecase */
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07006997 if (is_voip_rx) {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08006998 if (!voice_extn_is_compress_voip_supported()) {
6999 if (out->sample_rate == 8000 || out->sample_rate == 16000 ||
7000 out->sample_rate == 32000 || out->sample_rate == 48000) {
Aniket Kumar Lata4f9a2a52019-05-09 18:44:09 -07007001 out->channel_mask = audio_extn_utils_is_vendor_enhanced_fwk() ?
7002 AUDIO_CHANNEL_OUT_MONO : AUDIO_CHANNEL_OUT_STEREO;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007003 out->usecase = USECASE_AUDIO_PLAYBACK_VOIP;
7004 out->format = AUDIO_FORMAT_PCM_16_BIT;
Vikram Panduranga93f080e2017-06-07 18:16:14 -07007005
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007006 out->config = default_pcm_config_voip_copp;
7007 out->config.period_size = VOIP_IO_BUF_SIZE(out->sample_rate, DEFAULT_VOIP_BUF_DURATION_MS, DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
7008 out->config.rate = out->sample_rate;
7009 }
7010 } else {
7011 if ((out->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
7012 voice_extn_compress_voip_is_active(out->dev)) &&
7013 (voice_extn_compress_voip_is_config_supported(config))) {
7014 ret = voice_extn_compress_voip_open_output_stream(out);
7015 if (ret != 0) {
7016 ALOGE("%s: Compress voip output cannot be opened, error:%d",
7017 __func__, ret);
7018 goto error_open;
7019 }
7020 }
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007021 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007022 } else if (audio_is_linear_pcm(out->format) &&
7023 out->flags == AUDIO_OUTPUT_FLAG_NONE && is_usb_dev) {
7024 out->channel_mask = config->channel_mask;
7025 out->sample_rate = config->sample_rate;
7026 out->format = config->format;
7027 out->usecase = USECASE_AUDIO_PLAYBACK_HIFI;
7028 // does this change?
7029 out->config = is_hdmi ? pcm_config_hdmi_multi : pcm_config_hifi;
7030 out->config.rate = config->sample_rate;
7031 out->config.channels = audio_channel_count_from_out_mask(out->channel_mask);
7032 out->config.period_size = HDMI_MULTI_PERIOD_BYTES / (out->config.channels *
7033 audio_bytes_per_sample(config->format));
7034 out->config.format = pcm_format_from_audio_format(out->format);
vivek mehta0ea887a2015-08-26 14:01:20 -07007035 } else if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307036 (out->flags == AUDIO_OUTPUT_FLAG_DIRECT)) {
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307037 pthread_mutex_lock(&adev->lock);
7038 bool offline = (adev->card_status == CARD_STATUS_OFFLINE);
7039 pthread_mutex_unlock(&adev->lock);
7040
7041 // reject offload during card offline to allow
7042 // fallback to s/w paths
7043 if (offline) {
7044 ret = -ENODEV;
7045 goto error_open;
7046 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007047
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007048 if (config->offload_info.version != AUDIO_INFO_INITIALIZER.version ||
7049 config->offload_info.size != AUDIO_INFO_INITIALIZER.size) {
7050 ALOGE("%s: Unsupported Offload information", __func__);
7051 ret = -EINVAL;
7052 goto error_open;
7053 }
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007054
Atul Khare3fa6e542017-08-09 00:56:17 +05307055 if (config->offload_info.format == 0)
7056 config->offload_info.format = config->format;
7057 if (config->offload_info.sample_rate == 0)
7058 config->offload_info.sample_rate = config->sample_rate;
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007059
Mingming Yin90310102013-11-13 16:57:00 -08007060 if (!is_supported_format(config->offload_info.format) &&
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307061 !audio_extn_passthru_is_supported_format(config->offload_info.format)) {
vivek mehta0ea887a2015-08-26 14:01:20 -07007062 ALOGE("%s: Unsupported audio format %x " , __func__, config->offload_info.format);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007063 ret = -EINVAL;
7064 goto error_open;
7065 }
7066
Ben Romberger0f8c87b2017-05-24 17:41:11 -07007067 /* TrueHD only supported for 48k multiples (48k, 96k, 192k) */
7068 if ((config->offload_info.format == AUDIO_FORMAT_DOLBY_TRUEHD) &&
7069 (audio_extn_passthru_is_passthrough_stream(out)) &&
7070 !((config->sample_rate == 48000) ||
7071 (config->sample_rate == 96000) ||
7072 (config->sample_rate == 192000))) {
7073 ALOGE("%s: Unsupported sample rate %d for audio format %x",
7074 __func__, config->sample_rate, config->offload_info.format);
7075 ret = -EINVAL;
7076 goto error_open;
7077 }
7078
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007079 out->compr_config.codec = (struct snd_codec *)
7080 calloc(1, sizeof(struct snd_codec));
7081
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007082 if (!out->compr_config.codec) {
7083 ret = -ENOMEM;
7084 goto error_open;
7085 }
7086
Dhananjay Kumarac341582017-02-23 23:42:25 +05307087 out->stream.pause = out_pause;
7088 out->stream.resume = out_resume;
7089 out->stream.flush = out_flush;
Ashish Jain4847e9d2017-08-17 19:16:57 +05307090 out->stream.set_callback = out_set_callback;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307091 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
Mingming Yin21d60472015-09-30 13:56:25 -07007092 out->stream.drain = out_drain;
Dhananjay Kumarac341582017-02-23 23:42:25 +05307093 out->usecase = get_offload_usecase(adev, true /* is_compress */);
vivek mehta446c3962015-09-14 10:57:35 -07007094 ALOGV("Compress Offload usecase .. usecase selected %d", out->usecase);
Dhananjay Kumarac341582017-02-23 23:42:25 +05307095 } else {
7096 out->usecase = get_offload_usecase(adev, false /* is_compress */);
7097 ALOGV("non-offload DIRECT_usecase ... usecase selected %d ", out->usecase);
vivek mehta0ea887a2015-08-26 14:01:20 -07007098 }
vivek mehta446c3962015-09-14 10:57:35 -07007099
7100 if (out->usecase == USECASE_INVALID) {
Mingming Yin3a941d42016-02-17 18:08:05 -08007101 if (out->devices & AUDIO_DEVICE_OUT_AUX_DIGITAL &&
7102 config->format == 0 && config->sample_rate == 0 &&
7103 config->channel_mask == 0) {
Mingming Yin21854652016-04-13 11:54:02 -07007104 ALOGI("%s dummy open to query sink capability",__func__);
Mingming Yin3a941d42016-02-17 18:08:05 -08007105 out->usecase = USECASE_AUDIO_PLAYBACK_OFFLOAD;
7106 } else {
7107 ALOGE("%s, Max allowed OFFLOAD usecase reached ... ", __func__);
7108 ret = -EEXIST;
7109 goto error_open;
7110 }
vivek mehta446c3962015-09-14 10:57:35 -07007111 }
7112
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007113 if (config->offload_info.channel_mask)
7114 out->channel_mask = config->offload_info.channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007115 else if (config->channel_mask) {
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007116 out->channel_mask = config->channel_mask;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007117 config->offload_info.channel_mask = config->channel_mask;
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007118 } else {
Dhananjay Kumarac341582017-02-23 23:42:25 +05307119 ALOGE("out->channel_mask not set for OFFLOAD/DIRECT usecase");
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007120 ret = -EINVAL;
7121 goto error_open;
ApurupaPattapuc6a3a9e2014-01-10 14:46:02 -08007122 }
Haynes Mathew Georgea99f7532016-08-24 16:01:21 -07007123
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007124 format = out->format = config->offload_info.format;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007125 out->sample_rate = config->offload_info.sample_rate;
7126
Mingming Yin3ee55c62014-08-04 14:23:35 -07007127 out->bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007128
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307129 out->compr_config.codec->id = get_snd_codec_id(config->offload_info.format);
Satish Babu Patakokila5933e972017-08-24 12:22:08 +05307130 if (audio_extn_utils_is_dolby_format(config->offload_info.format)) {
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307131 audio_extn_dolby_send_ddp_endp_params(adev);
7132 audio_extn_dolby_set_dmid(adev);
7133 }
vivek mehta0ea887a2015-08-26 14:01:20 -07007134
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007135 out->compr_config.codec->sample_rate =
Ravi Kumar Alamandab91bff32014-11-14 12:05:54 -08007136 config->offload_info.sample_rate;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007137 out->compr_config.codec->bit_rate =
7138 config->offload_info.bit_rate;
7139 out->compr_config.codec->ch_in =
Dhanalakshmi Siddania15c6792016-08-10 15:33:53 +05307140 audio_channel_count_from_out_mask(out->channel_mask);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007141 out->compr_config.codec->ch_out = out->compr_config.codec->ch_in;
Satish Babu Patakokilaa395a9e2016-11-01 12:18:49 +05307142 /* Update bit width only for non passthrough usecases.
7143 * For passthrough usecases, the output will always be opened @16 bit
7144 */
7145 if (!audio_extn_passthru_is_passthrough_stream(out))
7146 out->bit_width = AUDIO_OUTPUT_BIT_WIDTH;
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307147
7148 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP)
7149 out->compr_config.codec->flags |= COMPRESSED_TIMESTAMP_FLAG;
7150 ALOGVV("%s : out->compr_config.codec->flags -> (%#x) ", __func__, out->compr_config.codec->flags);
7151
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007152 /*TODO: Do we need to change it for passthrough */
7153 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007154
Manish Dewangana6fc5442015-08-24 20:30:31 +05307155 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC)
7156 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_RAW;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307157 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_ADTS)
Manish Dewangana6fc5442015-08-24 20:30:31 +05307158 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4ADTS;
Arun Kumar Dasari3b174182016-12-27 13:01:14 +05307159 else if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) == AUDIO_FORMAT_AAC_LATM)
7160 out->compr_config.codec->format = SND_AUDIOSTREAMFORMAT_MP4LATM;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307161
7162 if ((config->offload_info.format & AUDIO_FORMAT_MAIN_MASK) ==
7163 AUDIO_FORMAT_PCM) {
7164
7165 /*Based on platform support, configure appropriate alsa format for corresponding
7166 *hal input format.
7167 */
7168 out->compr_config.codec->format = hal_format_to_alsa(
7169 config->offload_info.format);
7170
Ashish Jain83a6cc22016-06-28 14:34:17 +05307171 out->hal_op_format = alsa_format_to_hal(
Ashish Jainf1eaa582016-05-23 20:54:24 +05307172 out->compr_config.codec->format);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307173 out->hal_ip_format = out->format;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307174
Dhananjay Kumarac341582017-02-23 23:42:25 +05307175 /*for direct non-compress playback populate bit_width based on selected alsa format as
Ashish Jainf1eaa582016-05-23 20:54:24 +05307176 *hal input format and alsa format might differ based on platform support.
7177 */
7178 out->bit_width = audio_bytes_per_sample(
Ashish Jain83a6cc22016-06-28 14:34:17 +05307179 out->hal_op_format) << 3;
Ashish Jainf1eaa582016-05-23 20:54:24 +05307180
7181 out->compr_config.fragments = DIRECT_PCM_NUM_FRAGMENTS;
7182
7183 /* Check if alsa session is configured with the same format as HAL input format,
7184 * if not then derive correct fragment size needed to accomodate the
7185 * conversion of HAL input format to alsa format.
7186 */
7187 audio_extn_utils_update_direct_pcm_fragment_size(out);
7188
7189 /*if hal input and output fragment size is different this indicates HAL input format is
7190 *not same as the alsa format
7191 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307192 if (out->hal_fragment_size != out->compr_config.fragment_size) {
Ashish Jainf1eaa582016-05-23 20:54:24 +05307193 /*Allocate a buffer to convert input data to the alsa configured format.
7194 *size of convert buffer is equal to the size required to hold one fragment size
7195 *worth of pcm data, this is because flinger does not write more than fragment_size
7196 */
Ashish Jain83a6cc22016-06-28 14:34:17 +05307197 out->convert_buffer = calloc(1,out->compr_config.fragment_size);
7198 if (out->convert_buffer == NULL){
Ashish Jainf1eaa582016-05-23 20:54:24 +05307199 ALOGE("Allocation failed for convert buffer for size %d", out->compr_config.fragment_size);
7200 ret = -ENOMEM;
7201 goto error_open;
7202 }
7203 }
7204 } else if (audio_extn_passthru_is_passthrough_stream(out)) {
7205 out->compr_config.fragment_size =
7206 audio_extn_passthru_get_buffer_size(&config->offload_info);
7207 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7208 } else {
7209 out->compr_config.fragment_size =
7210 platform_get_compress_offload_buffer_size(&config->offload_info);
7211 out->compr_config.fragments = COMPRESS_OFFLOAD_NUM_FRAGMENTS;
7212 }
Mingming Yin3ee55c62014-08-04 14:23:35 -07007213
Naresh Tanniruee3499a2017-01-05 14:05:35 +05307214 if (out->flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7215 out->compr_config.fragment_size += sizeof(struct snd_codec_metadata);
7216 }
Amit Shekhar6f461b12014-08-01 14:52:58 -07007217 if (config->offload_info.format == AUDIO_FORMAT_FLAC)
Satya Krishna Pindiproli5d82d012015-08-12 18:21:25 +05307218 out->compr_config.codec->options.flac_dec.sample_size = AUDIO_OUTPUT_BIT_WIDTH;
Mingming Yin3ee55c62014-08-04 14:23:35 -07007219
Dhanalakshmi Siddani18737932016-11-29 17:33:17 +05307220 if (config->offload_info.format == AUDIO_FORMAT_APTX) {
7221 audio_extn_send_aptx_dec_bt_addr_to_dsp(out);
7222 }
7223
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007224 if (flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING)
7225 out->non_blocking = 1;
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007226
Manish Dewangan69426c82017-01-30 17:35:36 +05307227 if ((flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) &&
7228 (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC)) {
7229 out->render_mode = RENDER_MODE_AUDIO_STC_MASTER;
7230 } else if(flags & AUDIO_OUTPUT_FLAG_TIMESTAMP) {
7231 out->render_mode = RENDER_MODE_AUDIO_MASTER;
7232 } else {
7233 out->render_mode = RENDER_MODE_AUDIO_NO_TIMESTAMP;
7234 }
Alexy Josephaa54c872014-12-03 02:46:47 -08007235
Naresh Tanniru29bce4e2017-04-27 17:54:30 +05307236 memset(&out->channel_map_param, 0,
7237 sizeof(struct audio_out_channel_map_param));
7238
Haynes Mathew George352f27b2013-07-26 00:00:15 -07007239 out->send_new_metadata = 1;
Chaithanya Krishna Bacharajua70cb6a2015-07-24 14:15:05 +05307240 out->send_next_track_params = false;
7241 out->is_compr_metadata_avail = false;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007242 out->offload_state = OFFLOAD_STATE_IDLE;
7243 out->playback_started = 0;
Zhou Song48453a02018-01-10 17:50:59 +08007244 out->writeAt.tv_sec = 0;
7245 out->writeAt.tv_nsec = 0;
Haynes Mathew Georgeb9012ab2013-12-10 13:44:56 -08007246
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007247 audio_extn_dts_create_state_notifier_node(out->usecase);
7248
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007249 ALOGV("%s: offloaded output offload_info version %04x bit rate %d",
7250 __func__, config->offload_info.version,
7251 config->offload_info.bit_rate);
Ashish Jain5106d362016-05-11 19:23:33 +05307252
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307253 /* Check if DSD audio format is supported in codec
7254 * and there is no active native DSD use case
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307255 */
7256
7257 if ((config->format == AUDIO_FORMAT_DSD) &&
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307258 (!platform_check_codec_dsd_support(adev->platform) ||
7259 audio_is_dsd_native_stream_active(adev))) {
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307260 ret = -EINVAL;
7261 goto error_open;
7262 }
7263
Ashish Jain5106d362016-05-11 19:23:33 +05307264 /* Disable gapless if any of the following is true
7265 * passthrough playback
7266 * AV playback
Dhananjay Kumarac341582017-02-23 23:42:25 +05307267 * non compressed Direct playback
Ashish Jain5106d362016-05-11 19:23:33 +05307268 */
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307269 if (audio_extn_passthru_is_passthrough_stream(out) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307270 (config->format == AUDIO_FORMAT_DSD) ||
Naresh Tanniru928f0862017-04-07 16:44:23 -07007271 (config->format == AUDIO_FORMAT_IEC61937) ||
Preetam Singh Ranawatf5fbdd62016-09-29 18:38:31 +05307272 config->offload_info.has_video ||
Dhananjay Kumarac341582017-02-23 23:42:25 +05307273 !(out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) {
Ashish Jain5106d362016-05-11 19:23:33 +05307274 check_and_set_gapless_mode(adev, false);
7275 } else
7276 check_and_set_gapless_mode(adev, true);
Mingming Yin21854652016-04-13 11:54:02 -07007277
Satish Babu Patakokila1caa1b72016-05-24 13:47:08 +05307278 if (audio_extn_passthru_is_passthrough_stream(out)) {
Mingming Yin21854652016-04-13 11:54:02 -07007279 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7280 }
Preetam Singh Ranawatcb6212e2016-07-19 18:33:53 +05307281 if (config->format == AUDIO_FORMAT_DSD) {
7282 out->flags |= AUDIO_OUTPUT_FLAG_COMPRESS_PASSTHROUGH;
7283 out->compr_config.codec->compr_passthr = PASSTHROUGH_DSD;
7284 }
Aalique Grahame0359a1f2016-09-08 16:54:22 -07007285
7286 create_offload_callback_thread(out);
7287
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007288 } else if (out->flags & AUDIO_OUTPUT_FLAG_INCALL_MUSIC) {
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007289 switch (config->sample_rate) {
7290 case 0:
7291 out->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7292 break;
7293 case 8000:
7294 case 16000:
7295 case 48000:
7296 out->sample_rate = config->sample_rate;
7297 break;
7298 default:
7299 ALOGE("%s: Unsupported sampling rate %d for Incall Music", __func__,
7300 config->sample_rate);
7301 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7302 ret = -EINVAL;
7303 goto error_open;
7304 }
7305 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7306 switch (config->channel_mask) {
7307 case AUDIO_CHANNEL_NONE:
7308 case AUDIO_CHANNEL_OUT_STEREO:
7309 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7310 break;
7311 default:
7312 ALOGE("%s: Unsupported channel mask %#x for Incall Music", __func__,
7313 config->channel_mask);
7314 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7315 ret = -EINVAL;
7316 goto error_open;
7317 }
7318 switch (config->format) {
7319 case AUDIO_FORMAT_DEFAULT:
7320 case AUDIO_FORMAT_PCM_16_BIT:
7321 out->format = AUDIO_FORMAT_PCM_16_BIT;
7322 break;
7323 default:
7324 ALOGE("%s: Unsupported format %#x for Incall Music", __func__,
7325 config->format);
7326 config->format = AUDIO_FORMAT_PCM_16_BIT;
7327 ret = -EINVAL;
7328 goto error_open;
7329 }
7330
Satya Krishna Pindiprolif1cd92b2016-04-14 19:05:23 +05307331 ret = voice_extn_check_and_set_incall_music_usecase(adev, out);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007332 if (ret != 0) {
7333 ALOGE("%s: Incall music delivery usecase cannot be set error:%d",
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007334 __func__, ret);
Shiv Maliyappanahallif3b9a422013-10-22 16:38:08 -07007335 goto error_open;
7336 }
Arun Mirpuri7da752a2018-09-11 18:01:15 -07007337 } else if (out->devices == AUDIO_DEVICE_OUT_TELEPHONY_TX) {
Aalique Grahame22e49102018-12-18 14:23:57 -08007338 switch (config->sample_rate) {
7339 case 0:
7340 out->sample_rate = AFE_PROXY_SAMPLING_RATE;
7341 break;
7342 case 8000:
7343 case 16000:
7344 case 48000:
7345 out->sample_rate = config->sample_rate;
7346 break;
7347 default:
7348 ALOGE("%s: Unsupported sampling rate %d for Telephony TX", __func__,
7349 config->sample_rate);
7350 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
7351 ret = -EINVAL;
7352 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007353 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007354 //FIXME: add support for MONO stream configuration when audioflinger mixer supports it
7355 switch (config->channel_mask) {
7356 case AUDIO_CHANNEL_NONE:
7357 out->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7358 break;
7359 case AUDIO_CHANNEL_OUT_STEREO:
7360 out->channel_mask = config->channel_mask;
7361 break;
7362 default:
7363 ALOGE("%s: Unsupported channel mask %#x for Telephony TX", __func__,
7364 config->channel_mask);
7365 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7366 ret = -EINVAL;
7367 break;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007368 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007369 switch (config->format) {
7370 case AUDIO_FORMAT_DEFAULT:
7371 out->format = AUDIO_FORMAT_PCM_16_BIT;
7372 break;
7373 case AUDIO_FORMAT_PCM_16_BIT:
7374 out->format = config->format;
7375 break;
7376 default:
7377 ALOGE("%s: Unsupported format %#x for Telephony TX", __func__,
7378 config->format);
7379 config->format = AUDIO_FORMAT_PCM_16_BIT;
7380 ret = -EINVAL;
7381 break;
7382 }
7383 if (ret != 0)
7384 goto error_open;
7385
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007386 out->usecase = USECASE_AUDIO_PLAYBACK_AFE_PROXY;
7387 out->config = pcm_config_afe_proxy_playback;
Aalique Grahame22e49102018-12-18 14:23:57 -08007388 out->config.rate = out->sample_rate;
7389 out->config.channels =
7390 audio_channel_count_from_out_mask(out->channel_mask);
7391 out->config.format = pcm_format_from_audio_format(out->format);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007392 adev->voice_tx_output = out;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007393 } else {
Ashish Jain058165c2016-09-28 23:18:48 +05307394 unsigned int channels = 0;
7395 /*Update config params to default if not set by the caller*/
7396 if (config->sample_rate == 0)
7397 config->sample_rate = DEFAULT_OUTPUT_SAMPLING_RATE;
7398 if (config->channel_mask == AUDIO_CHANNEL_NONE)
7399 config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
7400 if (config->format == AUDIO_FORMAT_DEFAULT)
7401 config->format = AUDIO_FORMAT_PCM_16_BIT;
7402
7403 channels = audio_channel_count_from_out_mask(out->channel_mask);
7404
Varun Balaraje49253e2017-07-06 19:48:56 +05307405 if (out->flags & AUDIO_OUTPUT_FLAG_INTERACTIVE) {
7406 out->usecase = get_interactive_usecase(adev);
7407 out->config = pcm_config_low_latency;
7408 } else if (out->flags & AUDIO_OUTPUT_FLAG_RAW) {
Ashish Jain83a6cc22016-06-28 14:34:17 +05307409 out->usecase = USECASE_AUDIO_PLAYBACK_ULL;
Haynes Mathew George5beddd42016-06-27 18:33:40 -07007410 out->realtime = may_use_noirq_mode(adev, USECASE_AUDIO_PLAYBACK_ULL,
7411 out->flags);
7412 out->config = out->realtime ? pcm_config_rt : pcm_config_low_latency;
Haynes Mathew George16081042017-05-31 17:16:49 -07007413 } else if (out->flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
7414 out->usecase = USECASE_AUDIO_PLAYBACK_MMAP;
7415 out->config = pcm_config_mmap_playback;
7416 out->stream.start = out_start;
7417 out->stream.stop = out_stop;
7418 out->stream.create_mmap_buffer = out_create_mmap_buffer;
7419 out->stream.get_mmap_position = out_get_mmap_position;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307420 } else if (out->flags & AUDIO_OUTPUT_FLAG_FAST) {
7421 out->usecase = USECASE_AUDIO_PLAYBACK_LOW_LATENCY;
Aniket Kumar Lata932f4872017-11-06 18:29:44 -08007422 out->hal_output_suspend_supported =
7423 property_get_bool("vendor.audio.hal.output.suspend.supported", false);
7424 out->dynamic_pm_qos_config_supported =
7425 property_get_bool("vendor.audio.hal.dynamic.qos.config.supported", false);
7426 if (!out->dynamic_pm_qos_config_supported) {
Alexy Joseph98988832017-01-13 14:56:59 -08007427 ALOGI("%s: dynamic qos voting not enabled for platform", __func__);
7428 } else {
7429 ALOGI("%s: dynamic qos voting enabled for platform", __func__);
7430 //the mixer path will be a string similar to "low-latency-playback resume"
7431 strlcpy(out->pm_qos_mixer_path, use_case_table[out->usecase], MAX_MIXER_PATH_LEN);
7432 strlcat(out->pm_qos_mixer_path,
7433 " resume", MAX_MIXER_PATH_LEN);
7434 ALOGI("%s: created %s pm_qos_mixer_path" , __func__,
7435 out->pm_qos_mixer_path);
7436 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307437 out->config = pcm_config_low_latency;
7438 } else if (out->flags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) {
7439 out->usecase = USECASE_AUDIO_PLAYBACK_DEEP_BUFFER;
7440 out->config = pcm_config_deep_buffer;
Ashish Jain058165c2016-09-28 23:18:48 +05307441 out->config.period_size = get_output_period_size(config->sample_rate, out->format,
7442 channels, DEEP_BUFFER_OUTPUT_PERIOD_DURATION);
7443 if (out->config.period_size <= 0) {
7444 ALOGE("Invalid configuration period size is not valid");
7445 ret = -EINVAL;
7446 goto error_open;
7447 }
Aalique Grahame22e49102018-12-18 14:23:57 -08007448 } else if (flags & AUDIO_OUTPUT_FLAG_TTS) {
7449 out->usecase = USECASE_AUDIO_PLAYBACK_TTS;
7450 out->config = pcm_config_deep_buffer;
Vignesh Kulothungana6927272019-02-20 15:17:07 -08007451 } else if (config->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL) {
7452 out->usecase = USECASE_AUDIO_PLAYBACK_WITH_HAPTICS;
7453 out->config = pcm_config_haptics_audio;
7454 if (force_haptic_path)
7455 adev->haptics_config = pcm_config_haptics_audio;
7456 else
7457 adev->haptics_config = pcm_config_haptics;
7458
7459 out->config.channels =
7460 audio_channel_count_from_out_mask(out->channel_mask & ~AUDIO_CHANNEL_HAPTIC_ALL);
7461
7462 if (force_haptic_path) {
7463 out->config.channels = 1;
7464 adev->haptics_config.channels = 1;
7465 } else
7466 adev->haptics_config.channels = audio_channel_count_from_out_mask(out->channel_mask & AUDIO_CHANNEL_HAPTIC_ALL);
Derek Chenf6318be2017-06-12 17:16:24 -04007467 } else if (out->devices & AUDIO_DEVICE_OUT_BUS) {
7468 ret = audio_extn_auto_hal_open_output_stream(out);
7469 if (ret) {
7470 ALOGE("%s: Failed to open output stream for bus device", __func__);
7471 ret = -EINVAL;
7472 goto error_open;
7473 }
Ashish Jain83a6cc22016-06-28 14:34:17 +05307474 } else {
7475 /* primary path is the default path selected if no other outputs are available/suitable */
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007476 out->usecase = GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
7477 out->config = GET_PCM_CONFIG_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307478 }
7479 out->hal_ip_format = format = out->format;
7480 out->config.format = hal_format_to_pcm(out->hal_ip_format);
7481 out->hal_op_format = pcm_format_to_hal(out->config.format);
7482 out->bit_width = format_to_bitwidth_table[out->hal_op_format] << 3;
7483 out->config.rate = config->sample_rate;
Ravi Kumar Alamanda8f715d92013-11-01 20:37:38 -07007484 out->sample_rate = out->config.rate;
Ashish Jain058165c2016-09-28 23:18:48 +05307485 out->config.channels = channels;
Ashish Jain83a6cc22016-06-28 14:34:17 +05307486 if (out->hal_ip_format != out->hal_op_format) {
7487 uint32_t buffer_size = out->config.period_size *
7488 format_to_bitwidth_table[out->hal_op_format] *
7489 out->config.channels;
7490 out->convert_buffer = calloc(1, buffer_size);
7491 if (out->convert_buffer == NULL){
7492 ALOGE("Allocation failed for convert buffer for size %d",
7493 out->compr_config.fragment_size);
7494 ret = -ENOMEM;
7495 goto error_open;
7496 }
7497 ALOGD("Convert buffer allocated of size %d", buffer_size);
7498 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007499 }
7500
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007501 ALOGV("%s devices:%d, format:%x, out->sample_rate:%d,out->bit_width:%d out->format:%d out->flags:%x, flags: %x usecase %d",
7502 __func__, devices, format, out->sample_rate, out->bit_width, out->format, out->flags, flags, out->usecase);
Ashish Jain83a6cc22016-06-28 14:34:17 +05307503
Pradnya Chaphekar80a8cfb2014-10-20 16:17:01 -07007504 /* TODO remove this hardcoding and check why width is zero*/
7505 if (out->bit_width == 0)
7506 out->bit_width = 16;
Dhananjay Kumard6d32152016-10-13 16:11:03 +05307507 audio_extn_utils_update_stream_output_app_type_cfg(adev->platform,
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07007508 &adev->streams_output_cfg_list,
Aalique Grahame65780b52017-09-27 14:59:56 -07007509 devices, out->flags, out->hal_op_format, out->sample_rate,
Dhananjay Kumar4d91c1a2016-12-01 23:27:29 +05307510 out->bit_width, out->channel_mask, out->profile,
Manish Dewangan837dc462015-05-27 10:17:41 +05307511 &out->app_type_cfg);
Aalique Grahame6e763712019-01-31 16:18:17 -08007512 if ((out->usecase == (audio_usecase_t)(GET_USECASE_AUDIO_PLAYBACK_PRIMARY(use_db_as_primary))) ||
Haynes Mathew Georgebf143712013-12-03 13:02:53 -08007513 (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
7514 /* Ensure the default output is not selected twice */
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007515 if(adev->primary_output == NULL)
7516 adev->primary_output = out;
7517 else {
7518 ALOGE("%s: Primary output is already opened", __func__);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007519 ret = -EEXIST;
7520 goto error_open;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08007521 }
7522 }
7523
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007524 /* Check if this usecase is already existing */
7525 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella7ce05352014-04-17 20:00:41 -07007526 if ((get_usecase_from_list(adev, out->usecase) != NULL) &&
7527 (out->usecase != USECASE_COMPRESS_VOIP_CALL)) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007528 ALOGE("%s: Usecase (%d) is already present", __func__, out->usecase);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007529 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007530 ret = -EEXIST;
7531 goto error_open;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007532 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007533
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007534 pthread_mutex_unlock(&adev->lock);
7535
7536 out->stream.common.get_sample_rate = out_get_sample_rate;
7537 out->stream.common.set_sample_rate = out_set_sample_rate;
7538 out->stream.common.get_buffer_size = out_get_buffer_size;
7539 out->stream.common.get_channels = out_get_channels;
7540 out->stream.common.get_format = out_get_format;
7541 out->stream.common.set_format = out_set_format;
7542 out->stream.common.standby = out_standby;
7543 out->stream.common.dump = out_dump;
7544 out->stream.common.set_parameters = out_set_parameters;
7545 out->stream.common.get_parameters = out_get_parameters;
7546 out->stream.common.add_audio_effect = out_add_audio_effect;
7547 out->stream.common.remove_audio_effect = out_remove_audio_effect;
7548 out->stream.get_latency = out_get_latency;
7549 out->stream.set_volume = out_set_volume;
Aalique Grahame22e49102018-12-18 14:23:57 -08007550#ifdef NO_AUDIO_OUT
7551 out->stream.write = out_write_for_no_output;
7552#else
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007553 out->stream.write = out_write;
Aalique Grahame22e49102018-12-18 14:23:57 -08007554#endif
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007555 out->stream.get_render_position = out_get_render_position;
7556 out->stream.get_next_write_timestamp = out_get_next_write_timestamp;
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007557 out->stream.get_presentation_position = out_get_presentation_position;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007558
Haynes Mathew George16081042017-05-31 17:16:49 -07007559 if (out->realtime)
7560 out->af_period_multiplier = af_period_multiplier;
7561 else
7562 out->af_period_multiplier = 1;
7563
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007564 out->standby = 1;
Eric Laurenta9024de2013-04-04 09:19:12 -07007565 /* out->muted = false; by calloc() */
Glenn Kasten2ccd7ba2013-09-10 09:04:31 -07007566 /* out->written = 0; by calloc() */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007567
7568 config->format = out->stream.common.get_format(&out->stream.common);
7569 config->channel_mask = out->stream.common.get_channels(&out->stream.common);
7570 config->sample_rate = out->stream.common.get_sample_rate(&out->stream.common);
Naresh Tanniru04f71882018-06-26 17:46:22 +05307571 register_format(out->format, out->supported_formats);
7572 register_channel_mask(out->channel_mask, out->supported_channel_masks);
7573 register_sample_rate(out->sample_rate, out->supported_sample_rates);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007574
Aalique Grahame22e49102018-12-18 14:23:57 -08007575 out->error_log = error_log_create(
7576 ERROR_LOG_ENTRIES,
7577 1000000000 /* aggregate consecutive identical errors within one second in ns */);
7578
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307579 /*
7580 By locking output stream before registering, we allow the callback
7581 to update stream's state only after stream's initial state is set to
7582 adev state.
7583 */
7584 lock_output_stream(out);
7585 audio_extn_snd_mon_register_listener(out, out_snd_mon_cb);
7586 pthread_mutex_lock(&adev->lock);
7587 out->card_status = adev->card_status;
7588 pthread_mutex_unlock(&adev->lock);
7589 pthread_mutex_unlock(&out->lock);
7590
Aalique Grahame22e49102018-12-18 14:23:57 -08007591 stream_app_type_cfg_init(&out->app_type_cfg);
7592
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007593 *stream_out = &out->stream;
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307594 ALOGD("%s: Stream (%p) picks up usecase (%s)", __func__, &out->stream,
vivek mehta0ea887a2015-08-26 14:01:20 -07007595 use_case_table[out->usecase]);
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007596
7597 if (out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
7598 audio_extn_dts_notify_playback_state(out->usecase, 0, out->sample_rate,
7599 popcount(out->channel_mask), out->playback_started);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007600 /* setup a channel for client <--> adsp communication for stream events */
Manish Dewangan21a850a2017-08-14 12:03:55 +05307601 is_direct_passthough = audio_extn_passthru_is_direct_passthrough(out);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007602 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) ||
Naresh Tanniru85819452017-05-04 18:55:45 -07007603 (out->flags & AUDIO_OUTPUT_FLAG_DIRECT_PCM) ||
Gangadhar Sb0210342019-02-22 17:39:41 +05307604 audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform) ||
7605 (audio_extn_ip_hdlr_intf_supported(config->format, is_direct_passthough, false))) {
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007606 hdlr_stream_cfg.pcm_device_id = platform_get_pcm_device_id(
7607 out->usecase, PCM_PLAYBACK);
7608 hdlr_stream_cfg.flags = out->flags;
7609 hdlr_stream_cfg.type = PCM_PLAYBACK;
7610 ret = audio_extn_adsp_hdlr_stream_open(&out->adsp_hdlr_stream_handle,
7611 &hdlr_stream_cfg);
7612 if (ret) {
7613 ALOGE("%s: adsp_hdlr_stream_open failed %d",__func__, ret);
7614 out->adsp_hdlr_stream_handle = NULL;
7615 }
7616 }
Gangadhar Sb0210342019-02-22 17:39:41 +05307617 ip_hdlr_stream = audio_extn_ip_hdlr_intf_supported(config->format,
7618 is_direct_passthough, false);
7619 ip_hdlr_dev = audio_extn_ip_hdlr_intf_supported_for_copp(adev->platform);
7620 if (ip_hdlr_stream || ip_hdlr_dev ) {
Vidyakumar Athota2062f912017-06-27 14:46:15 -07007621 ret = audio_extn_ip_hdlr_intf_init(&out->ip_hdlr_handle, NULL, NULL, adev, out->usecase);
Naresh Tanniru85819452017-05-04 18:55:45 -07007622 if (ret < 0) {
7623 ALOGE("%s: audio_extn_ip_hdlr_intf_init failed %d",__func__, ret);
7624 out->ip_hdlr_handle = NULL;
7625 }
7626 }
Derek Chenf939fb72018-11-13 13:34:41 -08007627
7628 streams_output_ctxt_t *out_ctxt = (streams_output_ctxt_t *)
7629 calloc(1, sizeof(streams_output_ctxt_t));
7630 if (out_ctxt == NULL) {
7631 ALOGE("%s fail to allocate output ctxt", __func__);
7632 ret = -ENOMEM;
7633 goto error_open;
7634 }
7635 out_ctxt->output = out;
7636
7637 pthread_mutex_lock(&adev->lock);
7638 list_add_tail(&adev->active_outputs_list, &out_ctxt->list);
7639 pthread_mutex_unlock(&adev->lock);
7640
Eric Laurent994a6932013-07-17 11:51:42 -07007641 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007642 return 0;
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007643
7644error_open:
Ashish Jain83a6cc22016-06-28 14:34:17 +05307645 if (out->convert_buffer)
7646 free(out->convert_buffer);
Ravi Kumar Alamandab1995062013-03-21 23:18:20 -07007647 free(out);
7648 *stream_out = NULL;
7649 ALOGD("%s: exit: ret %d", __func__, ret);
7650 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007651}
7652
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05307653void adev_close_output_stream(struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007654 struct audio_stream_out *stream)
7655{
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007656 struct stream_out *out = (struct stream_out *)stream;
7657 struct audio_device *adev = out->dev;
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007658 int ret = 0;
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007659
Haynes Mathew George484e8d22017-07-31 18:55:17 -07007660 ALOGD("%s: enter:stream_handle(%s)",__func__, use_case_table[out->usecase]);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05307661
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05307662 // must deregister from sndmonitor first to prevent races
7663 // between the callback and close_stream
7664 audio_extn_snd_mon_unregister_listener(out);
7665
Ben Rombergerd771a7c2017-02-22 18:05:17 -08007666 /* close adsp hdrl session before standby */
7667 if (out->adsp_hdlr_stream_handle) {
7668 ret = audio_extn_adsp_hdlr_stream_close(out->adsp_hdlr_stream_handle);
7669 if (ret)
7670 ALOGE("%s: adsp_hdlr_stream_close failed %d",__func__, ret);
7671 out->adsp_hdlr_stream_handle = NULL;
7672 }
7673
Manish Dewangan21a850a2017-08-14 12:03:55 +05307674 if (out->ip_hdlr_handle) {
Naresh Tanniru85819452017-05-04 18:55:45 -07007675 audio_extn_ip_hdlr_intf_deinit(out->ip_hdlr_handle);
7676 out->ip_hdlr_handle = NULL;
7677 }
7678
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007679 if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307680 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007681 ret = voice_extn_compress_voip_close_output_stream(&stream->common);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307682 out->started = 0;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05307683 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007684 if(ret != 0)
7685 ALOGE("%s: Compress voip output cannot be closed, error:%d",
7686 __func__, ret);
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007687 } else
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08007688 out_standby(&stream->common);
7689
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007690 if (is_offload_usecase(out->usecase)) {
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08007691 audio_extn_dts_remove_state_notifier_node(out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007692 destroy_offload_callback_thread(out);
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07007693 free_offload_usecase(adev, out->usecase);
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007694 if (out->compr_config.codec != NULL)
7695 free(out->compr_config.codec);
7696 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007697
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05307698 out->a2dp_compress_mute = false;
7699
Varun Balaraje49253e2017-07-06 19:48:56 +05307700 if (is_interactive_usecase(out->usecase))
7701 free_interactive_usecase(adev, out->usecase);
7702
Ashish Jain83a6cc22016-06-28 14:34:17 +05307703 if (out->convert_buffer != NULL) {
7704 free(out->convert_buffer);
7705 out->convert_buffer = NULL;
7706 }
7707
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07007708 if (adev->voice_tx_output == out)
7709 adev->voice_tx_output = NULL;
7710
Aalique Grahame22e49102018-12-18 14:23:57 -08007711 error_log_destroy(out->error_log);
7712 out->error_log = NULL;
7713
Dhanalakshmi Siddani6c3d0992017-01-16 16:52:33 +05307714 if (adev->primary_output == out)
7715 adev->primary_output = NULL;
7716
Ravi Kumar Alamanda4e02e552013-07-17 15:22:04 -07007717 pthread_cond_destroy(&out->cond);
7718 pthread_mutex_destroy(&out->lock);
Derek Chenf939fb72018-11-13 13:34:41 -08007719
7720 pthread_mutex_lock(&adev->lock);
7721 streams_output_ctxt_t *out_ctxt = out_get_stream(adev, out->handle);
7722 if (out_ctxt != NULL) {
7723 list_remove(&out_ctxt->list);
7724 free(out_ctxt);
7725 } else {
7726 ALOGW("%s, output stream already closed", __func__);
7727 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007728 free(stream);
Derek Chenf939fb72018-11-13 13:34:41 -08007729 pthread_mutex_unlock(&adev->lock);
Eric Laurent994a6932013-07-17 11:51:42 -07007730 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007731}
7732
7733static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
7734{
7735 struct audio_device *adev = (struct audio_device *)dev;
7736 struct str_parms *parms;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007737 char value[32];
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007738 int val;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007739 int ret;
7740 int status = 0;
Aalique Grahame22e49102018-12-18 14:23:57 -08007741 bool a2dp_reconfig = false;
Zhou Songd6d71752019-05-21 18:08:51 +08007742 struct listnode *node;
7743 struct audio_usecase *usecase = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007744
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007745 ALOGD("%s: enter: %s", __func__, kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007746 parms = str_parms_create_str(kvpairs);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007747
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307748 if (!parms)
7749 goto error;
Naresh Tanniru4c630392014-05-12 01:05:52 +05307750
Zhou Songd6d71752019-05-21 18:08:51 +08007751 pthread_mutex_lock(&adev->lock);
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307752 ret = str_parms_get_str(parms, "BT_SCO", value, sizeof(value));
7753 if (ret >= 0) {
7754 /* When set to false, HAL should disable EC and NS */
Zhou Songd6d71752019-05-21 18:08:51 +08007755 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0){
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307756 adev->bt_sco_on = true;
Zhou Songd6d71752019-05-21 18:08:51 +08007757 } else {
7758 ALOGD("sco is off, reset sco and route device to handset/mic");
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307759 adev->bt_sco_on = false;
Zhou Songd6d71752019-05-21 18:08:51 +08007760 audio_extn_sco_reset_configuration();
7761 list_for_each(node, &adev->usecase_list) {
7762 usecase = node_to_item(node, struct audio_usecase, list);
7763 if ((usecase->type == PCM_PLAYBACK) && usecase->stream.out &&
7764 (usecase->stream.out->devices & AUDIO_DEVICE_OUT_ALL_SCO))
7765 usecase->stream.out->devices = AUDIO_DEVICE_OUT_EARPIECE;
7766 else if ((usecase->type == PCM_CAPTURE) && usecase->stream.in &&
7767 (usecase->stream.in->device & AUDIO_DEVICE_IN_ALL_SCO))
7768 usecase->stream.in->device = AUDIO_DEVICE_IN_BUILTIN_MIC;
7769 else
7770 continue;
7771 select_devices(adev, usecase->id);
7772 }
7773 }
Ashish Jain1b9b30c2017-05-18 20:57:40 +05307774 }
7775
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007776 status = voice_set_parameters(adev, parms);
7777 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007778 goto done;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007779
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007780 status = platform_set_parameters(adev->platform, parms);
7781 if (status != 0)
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007782 goto done;
7783
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007784 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_NREC, value, sizeof(value));
7785 if (ret >= 0) {
Vicky Sehrawate240e5d2014-08-12 17:17:04 -07007786 /* When set to false, HAL should disable EC and NS */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007787 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7788 adev->bluetooth_nrec = true;
7789 else
7790 adev->bluetooth_nrec = false;
7791 }
7792
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007793 ret = str_parms_get_str(parms, "screen_state", value, sizeof(value));
7794 if (ret >= 0) {
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007795 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7796 adev->screen_off = false;
7797 else
7798 adev->screen_off = true;
7799 }
7800
Eric Laurent4b084132018-10-19 17:33:43 -07007801 ret = str_parms_get_int(parms, "rotation", &val);
7802 if (ret >= 0) {
7803 bool reverse_speakers = false;
7804 int camera_rotation = CAMERA_ROTATION_LANDSCAPE;
7805 switch (val) {
7806 // FIXME: note that the code below assumes that the speakers are in the correct placement
7807 // relative to the user when the device is rotated 90deg from its default rotation. This
7808 // assumption is device-specific, not platform-specific like this code.
7809 case 270:
7810 reverse_speakers = true;
7811 camera_rotation = CAMERA_ROTATION_INVERT_LANDSCAPE;
7812 break;
7813 case 0:
7814 case 180:
7815 camera_rotation = CAMERA_ROTATION_PORTRAIT;
7816 break;
7817 case 90:
7818 camera_rotation = CAMERA_ROTATION_LANDSCAPE;
7819 break;
7820 default:
7821 ALOGE("%s: unexpected rotation of %d", __func__, val);
7822 status = -EINVAL;
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007823 }
Eric Laurent4b084132018-10-19 17:33:43 -07007824 if (status == 0) {
7825 // check and set swap
7826 // - check if orientation changed and speaker active
7827 // - set rotation and cache the rotation value
7828 adev->camera_orientation =
7829 (adev->camera_orientation & ~CAMERA_ROTATION_MASK) | camera_rotation;
7830 if (!audio_extn_is_maxx_audio_enabled())
7831 platform_check_and_set_swap_lr_channels(adev, reverse_speakers);
7832 }
7833 }
Jean-Michel Trivic56336b2013-05-24 16:55:17 -07007834
Mingming Yin514a8bc2014-07-29 15:22:21 -07007835 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_BT_SCO_WB, value, sizeof(value));
7836 if (ret >= 0) {
7837 if (strcmp(value, AUDIO_PARAMETER_VALUE_ON) == 0)
7838 adev->bt_wb_speech_enabled = true;
7839 else
7840 adev->bt_wb_speech_enabled = false;
7841 }
7842
Zhou Song12c29502019-03-16 10:37:18 +08007843 ret = str_parms_get_str(parms, "bt_swb", value, sizeof(value));
7844 if (ret >= 0) {
7845 val = atoi(value);
7846 adev->swb_speech_mode = val;
7847 }
7848
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007849 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_CONNECT, value, sizeof(value));
7850 if (ret >= 0) {
7851 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307852 audio_devices_t device = (audio_devices_t) val;
Zhou Song681350a2017-10-19 16:28:42 +08007853 if (audio_is_output_device(val) &&
7854 (val & AUDIO_DEVICE_OUT_AUX_DIGITAL)) {
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007855 ALOGV("cache new ext disp type and edid");
7856 ret = platform_get_ext_disp_type(adev->platform);
7857 if (ret < 0) {
7858 ALOGE("%s: Failed to query disp type, ret:%d", __func__, ret);
Manisha Agarwal2f5ff882018-08-08 17:09:29 +05307859 } else {
7860 platform_cache_edid(adev->platform);
Shiv Maliyappanahallic0656402016-09-03 14:13:26 -07007861 }
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307862 } else if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
vivek mehta344576a2016-04-12 18:56:03 -07007863 /*
7864 * Do not allow AFE proxy port usage by WFD source when USB headset is connected.
7865 * Per AudioPolicyManager, USB device is higher priority than WFD.
7866 * For Voice call over USB headset, voice call audio is routed to AFE proxy ports.
7867 * If WFD use case occupies AFE proxy, it may result unintended behavior while
7868 * starting voice call on USB
7869 */
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007870 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307871 if (ret >= 0)
7872 audio_extn_usb_add_device(device, atoi(value));
7873
Zhou Song6f862822017-11-06 17:27:57 +08007874 if (!audio_extn_usb_is_tunnel_supported()) {
7875 ALOGV("detected USB connect .. disable proxy");
7876 adev->allow_afe_proxy_usage = false;
7877 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007878 }
7879 }
7880
7881 ret = str_parms_get_str(parms, AUDIO_PARAMETER_DEVICE_DISCONNECT, value, sizeof(value));
7882 if (ret >= 0) {
7883 val = atoi(value);
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307884 audio_devices_t device = (audio_devices_t) val;
Garmond Leunge3b6d482016-10-25 16:48:01 -07007885 /*
7886 * The HDMI / Displayport disconnect handling has been moved to
7887 * audio extension to ensure that its parameters are not
7888 * invalidated prior to updating sysfs of the disconnect event
7889 * Invalidate will be handled by audio_extn_ext_disp_set_parameters()
7890 */
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307891 if (audio_is_usb_out_device(device) || audio_is_usb_in_device(device)) {
Kuirong Wanga9f7cee2016-03-07 11:21:52 -08007892 ret = str_parms_get_str(parms, "card", value, sizeof(value));
Satya Krishna Pindiprolice227962017-12-13 16:07:14 +05307893 if (ret >= 0)
7894 audio_extn_usb_remove_device(device, atoi(value));
7895
Zhou Song6f862822017-11-06 17:27:57 +08007896 if (!audio_extn_usb_is_tunnel_supported()) {
7897 ALOGV("detected USB disconnect .. enable proxy");
7898 adev->allow_afe_proxy_usage = true;
7899 }
Pradnya Chaphekar4403bd72014-09-09 09:50:01 -07007900 }
7901 }
7902
Aalique Grahame22e49102018-12-18 14:23:57 -08007903 audio_extn_hfp_set_parameters(adev, parms);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08007904 audio_extn_qdsp_set_parameters(adev, parms);
Aalique Grahame22e49102018-12-18 14:23:57 -08007905
7906 status = audio_extn_a2dp_set_parameters(parms, &a2dp_reconfig);
Aniket Kumar Lata23300322019-02-20 22:25:30 -08007907 if (status >= 0 && a2dp_reconfig) {
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307908 struct audio_usecase *usecase;
7909 struct listnode *node;
7910 list_for_each(node, &adev->usecase_list) {
7911 usecase = node_to_item(node, struct audio_usecase, list);
Sujin Panicker390724d2019-04-26 10:43:36 +05307912 if (usecase->stream.out && (usecase->type == PCM_PLAYBACK) &&
Naresh Tanniruf7e9e632016-11-04 14:54:20 -07007913 (usecase->devices & AUDIO_DEVICE_OUT_ALL_A2DP)){
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307914 ALOGD("reconfigure a2dp... forcing device switch");
Weiyin Jiang425180d2017-06-05 16:40:23 +08007915
7916 pthread_mutex_unlock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307917 lock_output_stream(usecase->stream.out);
Weiyin Jiang425180d2017-06-05 16:40:23 +08007918 pthread_mutex_lock(&adev->lock);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307919 audio_extn_a2dp_set_handoff_mode(true);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307920 //force device switch to re configure encoder
7921 select_devices(adev, usecase->id);
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307922 audio_extn_a2dp_set_handoff_mode(false);
7923 pthread_mutex_unlock(&usecase->stream.out->lock);
Naresh Tanniru9d027a62015-03-13 01:32:10 +05307924 break;
7925 }
7926 }
7927 }
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08007928
7929 //handle vr audio setparam
7930 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
7931 value, sizeof(value));
7932 if (ret >= 0) {
7933 ALOGI("Setting vr mode to be %s", value);
7934 if (!strncmp(value, "true", 4)) {
7935 adev->vr_audio_mode_enabled = true;
7936 ALOGI("Setting vr mode to true");
7937 } else if (!strncmp(value, "false", 5)) {
7938 adev->vr_audio_mode_enabled = false;
7939 ALOGI("Setting vr mode to false");
7940 } else {
7941 ALOGI("wrong vr mode set");
7942 }
7943 }
7944
Eric Laurent4b084132018-10-19 17:33:43 -07007945 //FIXME: to be replaced by proper video capture properties API
7946 ret = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_CAMERA_FACING, value, sizeof(value));
7947 if (ret >= 0) {
7948 int camera_facing = CAMERA_FACING_BACK;
7949 if (strcmp(value, AUDIO_PARAMETER_VALUE_FRONT) == 0)
7950 camera_facing = CAMERA_FACING_FRONT;
7951 else if (strcmp(value, AUDIO_PARAMETER_VALUE_BACK) == 0)
7952 camera_facing = CAMERA_FACING_BACK;
7953 else {
7954 ALOGW("%s: invalid camera facing value: %s", __func__, value);
7955 goto done;
7956 }
7957 adev->camera_orientation =
7958 (adev->camera_orientation & ~CAMERA_FACING_MASK) | camera_facing;
7959 struct audio_usecase *usecase;
7960 struct listnode *node;
7961 list_for_each(node, &adev->usecase_list) {
7962 usecase = node_to_item(node, struct audio_usecase, list);
7963 struct stream_in *in = usecase->stream.in;
7964 if (usecase->type == PCM_CAPTURE && in != NULL &&
7965 in->source == AUDIO_SOURCE_CAMCORDER && !in->standby) {
7966 select_devices(adev, in->usecase);
7967 }
7968 }
7969 }
7970
Naresh Tannirucd2353e2016-08-19 00:37:25 +05307971 audio_extn_set_parameters(adev, parms);
Shiv Maliyappanahalli3e064fd2013-12-16 15:54:40 -08007972done:
7973 str_parms_destroy(parms);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08007974 pthread_mutex_unlock(&adev->lock);
Preetam Singh Ranawata5f32b42014-09-23 12:12:47 +05307975error:
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07007976 ALOGV("%s: exit with code(%d)", __func__, status);
7977 return status;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08007978}
7979
7980static char* adev_get_parameters(const struct audio_hw_device *dev,
7981 const char *keys)
7982{
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05307983 ALOGD("%s:%s", __func__, keys);
7984
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07007985 struct audio_device *adev = (struct audio_device *)dev;
7986 struct str_parms *reply = str_parms_create();
7987 struct str_parms *query = str_parms_create_str(keys);
7988 char *str;
Naresh Tannirud7205b62014-06-20 02:54:48 +05307989 char value[256] = {0};
7990 int ret = 0;
7991
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007992 if (!query || !reply) {
Alexy Josephaee4fdd2016-01-29 13:02:07 -08007993 if (reply) {
7994 str_parms_destroy(reply);
7995 }
7996 if (query) {
7997 str_parms_destroy(query);
7998 }
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07007999 ALOGE("adev_get_parameters: failed to create query or reply");
8000 return NULL;
8001 }
8002
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08008003 //handle vr audio getparam
8004
8005 ret = str_parms_get_str(query,
8006 AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8007 value, sizeof(value));
8008
8009 if (ret >= 0) {
8010 bool vr_audio_enabled = false;
8011 pthread_mutex_lock(&adev->lock);
8012 vr_audio_enabled = adev->vr_audio_mode_enabled;
8013 pthread_mutex_unlock(&adev->lock);
8014
8015 ALOGI("getting vr mode to %d", vr_audio_enabled);
8016
8017 if (vr_audio_enabled) {
8018 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8019 "true");
8020 goto exit;
8021 } else {
8022 str_parms_add_str(reply, AUDIO_PARAMETER_KEY_VR_AUDIO_MODE,
8023 "false");
8024 goto exit;
8025 }
8026 }
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008027
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008028 pthread_mutex_lock(&adev->lock);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008029 audio_extn_get_parameters(adev, query, reply);
Shiv Maliyappanahallif9308492013-12-12 12:18:09 -08008030 voice_get_parameters(adev, query, reply);
Aalique Grahame22e49102018-12-18 14:23:57 -08008031 audio_extn_a2dp_get_parameters(query, reply);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008032 platform_get_parameters(adev->platform, query, reply);
Naresh Tanniru80659832014-06-04 18:17:56 +05308033 pthread_mutex_unlock(&adev->lock);
8034
Naresh Tannirud7205b62014-06-20 02:54:48 +05308035exit:
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008036 str = str_parms_to_str(reply);
8037 str_parms_destroy(query);
8038 str_parms_destroy(reply);
8039
Sidipotu Ashokaa4fa6a2018-12-21 09:19:26 +05308040 ALOGD("%s: exit: returns - %s", __func__, str);
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008041 return str;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008042}
8043
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008044static int adev_init_check(const struct audio_hw_device *dev __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008045{
8046 return 0;
8047}
8048
8049static int adev_set_voice_volume(struct audio_hw_device *dev, float volume)
8050{
Haynes Mathew George5191a852013-09-11 14:19:36 -07008051 int ret;
8052 struct audio_device *adev = (struct audio_device *)dev;
Aalique Grahame22e49102018-12-18 14:23:57 -08008053
8054 audio_extn_extspk_set_voice_vol(adev->extspk, volume);
8055
Haynes Mathew George5191a852013-09-11 14:19:36 -07008056 pthread_mutex_lock(&adev->lock);
8057 /* cache volume */
Shruthi Krishnaace10852013-10-25 14:32:12 -07008058 ret = voice_set_volume(adev, volume);
Haynes Mathew George5191a852013-09-11 14:19:36 -07008059 pthread_mutex_unlock(&adev->lock);
8060 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008061}
8062
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008063static int adev_set_master_volume(struct audio_hw_device *dev __unused,
8064 float volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008065{
8066 return -ENOSYS;
8067}
8068
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008069static int adev_get_master_volume(struct audio_hw_device *dev __unused,
8070 float *volume __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008071{
8072 return -ENOSYS;
8073}
8074
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008075static int adev_set_master_mute(struct audio_hw_device *dev __unused,
8076 bool muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008077{
8078 return -ENOSYS;
8079}
8080
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008081static int adev_get_master_mute(struct audio_hw_device *dev __unused,
8082 bool *muted __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008083{
8084 return -ENOSYS;
8085}
8086
8087static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
8088{
8089 struct audio_device *adev = (struct audio_device *)dev;
Garmond Leung5fd0b552018-04-17 11:56:12 -07008090 struct listnode *node;
8091 struct audio_usecase *usecase = NULL;
8092 int ret = 0;
kunleizdc4af9d2017-05-04 12:15:35 +08008093
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008094 pthread_mutex_lock(&adev->lock);
8095 if (adev->mode != mode) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008096 ALOGD("%s: mode %d\n", __func__, mode);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008097 adev->mode = mode;
Kunlei Zhang1d5c7f22019-05-21 14:25:57 +08008098 if (voice_is_in_call(adev) &&
8099 (mode == AUDIO_MODE_NORMAL ||
8100 (mode == AUDIO_MODE_IN_COMMUNICATION && !voice_is_call_state_active(adev)))) {
Garmond Leung5fd0b552018-04-17 11:56:12 -07008101 list_for_each(node, &adev->usecase_list) {
8102 usecase = node_to_item(node, struct audio_usecase, list);
8103 if (usecase->type == VOICE_CALL)
8104 break;
8105 }
8106 if (usecase &&
8107 audio_is_usb_out_device(usecase->out_snd_device & AUDIO_DEVICE_OUT_ALL_USB)) {
8108 ret = audio_extn_usb_check_and_set_svc_int(usecase,
8109 true);
8110 if (ret != 0) {
8111 /* default service interval was successfully updated,
8112 reopen USB backend with new service interval */
8113 check_usecases_codec_backend(adev,
8114 usecase,
8115 usecase->out_snd_device);
8116 }
8117 }
8118
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008119 voice_stop_call(adev);
Banajit Goswami20cdd212015-09-11 01:11:30 -07008120 platform_set_gsm_mode(adev->platform, false);
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008121 adev->current_call_output = NULL;
kunleizdc4af9d2017-05-04 12:15:35 +08008122 // restore device for other active usecases after stop call
8123 list_for_each(node, &adev->usecase_list) {
8124 usecase = node_to_item(node, struct audio_usecase, list);
8125 select_devices(adev, usecase->id);
8126 }
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008127 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008128 }
8129 pthread_mutex_unlock(&adev->lock);
8130 return 0;
8131}
8132
8133static int adev_set_mic_mute(struct audio_hw_device *dev, bool state)
8134{
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008135 int ret;
Aalique Grahame22e49102018-12-18 14:23:57 -08008136 struct audio_device *adev = (struct audio_device *)dev;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008137
8138 pthread_mutex_lock(&adev->lock);
Vidyakumar Athota2850d532013-11-19 16:02:12 -08008139 ALOGD("%s state %d\n", __func__, state);
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008140 ret = voice_set_mic_mute((struct audio_device *)dev, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008141
Derek Chend2530072014-11-24 12:39:14 -08008142 if (adev->ext_hw_plugin)
8143 ret = audio_extn_ext_hw_plugin_set_mic_mute(adev->ext_hw_plugin, state);
Aalique Grahame22e49102018-12-18 14:23:57 -08008144
8145 adev->mic_muted = state;
Shiv Maliyappanahalli3bb73582013-11-05 12:49:15 -08008146 pthread_mutex_unlock(&adev->lock);
8147
8148 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008149}
8150
8151static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state)
8152{
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07008153 *state = voice_get_mic_mute((struct audio_device *)dev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008154 return 0;
8155}
8156
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008157static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev __unused,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008158 const struct audio_config *config)
8159{
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008160 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008161
Aalique Grahame22e49102018-12-18 14:23:57 -08008162 /* Don't know if USB HIFI in this context so use true to be conservative */
8163 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8164 true /*is_usb_hifi */) != 0)
8165 return 0;
8166
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008167 return get_input_buffer_size(config->sample_rate, config->format, channel_count,
8168 false /* is_low_latency: since we don't know, be conservative */);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008169}
8170
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008171static bool adev_input_allow_hifi_record(struct audio_device *adev,
8172 audio_devices_t devices,
8173 audio_input_flags_t flags,
8174 audio_source_t source) {
8175 const bool allowed = true;
8176
8177 if (!audio_is_usb_in_device(devices))
8178 return !allowed;
8179
8180 switch (flags) {
8181 case AUDIO_INPUT_FLAG_NONE:
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008182 break;
Haynes Mathew George59862182017-10-24 16:23:57 -07008183 case AUDIO_INPUT_FLAG_FAST: // disallow hifi record for FAST as
8184 // it affects RTD numbers over USB
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008185 default:
8186 return !allowed;
8187 }
8188
8189 switch (source) {
8190 case AUDIO_SOURCE_DEFAULT:
8191 case AUDIO_SOURCE_MIC:
8192 case AUDIO_SOURCE_UNPROCESSED:
8193 break;
8194 default:
8195 return !allowed;
8196 }
8197
8198 switch (adev->mode) {
8199 case 0:
8200 break;
8201 default:
8202 return !allowed;
8203 }
8204
8205 return allowed;
8206}
8207
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008208static int adev_update_voice_comm_input_stream(struct stream_in *in,
8209 struct audio_config *config)
8210{
8211 bool valid_rate = (config->sample_rate == 8000 ||
8212 config->sample_rate == 16000 ||
8213 config->sample_rate == 32000 ||
8214 config->sample_rate == 48000);
8215 bool valid_ch = audio_channel_count_from_in_mask(in->channel_mask) == 1;
8216
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008217 if(!voice_extn_is_compress_voip_supported()) {
kunleiz28c73e72019-03-27 17:24:04 +08008218 if (valid_rate && valid_ch) {
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008219 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8220 in->config = default_pcm_config_voip_copp;
8221 in->config.period_size = VOIP_IO_BUF_SIZE(in->sample_rate,
8222 DEFAULT_VOIP_BUF_DURATION_MS,
8223 DEFAULT_VOIP_BIT_DEPTH_BYTE)/2;
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008224 } else {
8225 ALOGW("%s No valid input in voip, use defaults"
8226 "sample rate %u, channel mask 0x%X",
8227 __func__, config->sample_rate, in->channel_mask);
8228 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008229 in->config.rate = config->sample_rate;
8230 in->sample_rate = config->sample_rate;
8231 } else {
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008232 //XXX needed for voice_extn_compress_voip_open_input_stream
8233 in->config.rate = config->sample_rate;
8234 if ((in->dev->mode == AUDIO_MODE_IN_COMMUNICATION ||
8235 voice_extn_compress_voip_is_active(in->dev)) &&
8236 (voice_extn_compress_voip_is_format_supported(in->format)) &&
8237 valid_rate && valid_ch) {
8238 voice_extn_compress_voip_open_input_stream(in);
8239 // update rate entries to match config from AF
8240 in->config.rate = config->sample_rate;
8241 in->sample_rate = config->sample_rate;
8242 } else {
8243 ALOGW("%s compress voip not active, use defaults", __func__);
8244 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008245 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008246 return 0;
8247}
8248
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008249static int adev_open_input_stream(struct audio_hw_device *dev,
Bharath Ramachandramurthy76d20892015-04-27 15:47:55 -07008250 audio_io_handle_t handle,
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008251 audio_devices_t devices,
8252 struct audio_config *config,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008253 struct audio_stream_in **stream_in,
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308254 audio_input_flags_t flags,
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008255 const char *address __unused,
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008256 audio_source_t source)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008257{
8258 struct audio_device *adev = (struct audio_device *)dev;
8259 struct stream_in *in;
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008260 int ret = 0, buffer_size, frame_size;
Ravi Kumar Alamandac3bc0812014-09-08 15:34:32 -07008261 int channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008262 bool is_low_latency = false;
Divya Narayanan Poojary45f19192016-09-30 18:52:13 +05308263 bool channel_mask_updated = false;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008264 bool is_usb_dev = audio_is_usb_in_device(devices);
8265 bool may_use_hifi_record = adev_input_allow_hifi_record(adev,
8266 devices,
8267 flags,
8268 source);
Andy Hung94320602018-10-29 18:31:12 -07008269 ALOGV("%s: enter: flags %#x, is_usb_dev %d, may_use_hifi_record %d,"
8270 " sample_rate %u, channel_mask %#x, format %#x",
8271 __func__, flags, is_usb_dev, may_use_hifi_record,
8272 config->sample_rate, config->channel_mask, config->format);
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308273
kunleizdff872d2018-08-20 14:40:33 +08008274 if (is_usb_dev && (!audio_extn_usb_connected(NULL))) {
kunleizd6a9e0c2018-07-30 15:38:52 +08008275 is_usb_dev = false;
8276 devices = AUDIO_DEVICE_IN_BUILTIN_MIC;
8277 ALOGW("%s: ignore set device to non existing USB card, use input device(%#x)",
8278 __func__, devices);
8279 }
8280
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008281 *stream_in = NULL;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008282
8283 if (!(is_usb_dev && may_use_hifi_record)) {
8284 if (config->sample_rate == 0)
8285 config->sample_rate = 48000;
8286 if (config->channel_mask == AUDIO_CHANNEL_NONE)
8287 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8288 if (config->format == AUDIO_FORMAT_DEFAULT)
8289 config->format = AUDIO_FORMAT_PCM_16_BIT;
8290
8291 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
8292
Aalique Grahame22e49102018-12-18 14:23:57 -08008293 if (check_input_parameters(config->sample_rate, config->format, channel_count,
8294 false) != 0)
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008295 return -EINVAL;
Chaithanya Krishna Bacharaju9955b162016-05-25 16:25:53 +05308296 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008297
8298 in = (struct stream_in *)calloc(1, sizeof(struct stream_in));
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07008299
8300 if (!in) {
8301 ALOGE("failed to allocate input stream");
8302 return -ENOMEM;
8303 }
8304
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308305 ALOGD("%s: enter: sample_rate(%d) channel_mask(%#x) devices(%#x)\
Manish Dewanganba9fcfa2016-03-24 16:20:06 +05308306 stream_handle(%p) io_handle(%d) source(%d) format %x",__func__, config->sample_rate,
8307 config->channel_mask, devices, &in->stream, handle, source, config->format);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008308 pthread_mutex_init(&in->lock, (const pthread_mutexattr_t *) NULL);
Shiv Maliyappanahalli736d4ce2015-09-28 15:23:06 -07008309 pthread_mutex_init(&in->pre_lock, (const pthread_mutexattr_t *) NULL);
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07008310
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008311 in->stream.common.get_sample_rate = in_get_sample_rate;
8312 in->stream.common.set_sample_rate = in_set_sample_rate;
8313 in->stream.common.get_buffer_size = in_get_buffer_size;
8314 in->stream.common.get_channels = in_get_channels;
8315 in->stream.common.get_format = in_get_format;
8316 in->stream.common.set_format = in_set_format;
8317 in->stream.common.standby = in_standby;
8318 in->stream.common.dump = in_dump;
8319 in->stream.common.set_parameters = in_set_parameters;
8320 in->stream.common.get_parameters = in_get_parameters;
8321 in->stream.common.add_audio_effect = in_add_audio_effect;
8322 in->stream.common.remove_audio_effect = in_remove_audio_effect;
8323 in->stream.set_gain = in_set_gain;
8324 in->stream.read = in_read;
8325 in->stream.get_input_frames_lost = in_get_input_frames_lost;
Aalique Grahame22e49102018-12-18 14:23:57 -08008326 in->stream.get_capture_position = in_get_capture_position;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05308327 in->stream.get_active_microphones = in_get_active_microphones;
Paul McLeana50b7332018-12-17 08:24:21 -07008328 in->stream.set_microphone_direction = in_set_microphone_direction;
8329 in->stream.set_microphone_field_dimension = in_set_microphone_field_dimension;
juyuchendb308c22019-01-21 11:57:17 -07008330 in->stream.update_sink_metadata = in_update_sink_metadata;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008331
8332 in->device = devices;
Vidyakumar Athota5c398212015-03-31 21:53:21 -07008333 in->source = source;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008334 in->dev = adev;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008335 in->standby = 1;
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008336 in->capture_handle = handle;
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008337 in->flags = flags;
Haynes Mathew George46740472017-10-27 18:40:12 -07008338 in->bit_width = 16;
8339 in->af_period_multiplier = 1;
justinweng20fb6d82019-02-21 18:49:00 -07008340 in->direction = MIC_DIRECTION_UNSPECIFIED;
8341 in->zoom = 0;
Haynes Mathew George46740472017-10-27 18:40:12 -07008342
Andy Hung94320602018-10-29 18:31:12 -07008343 ALOGV("%s: source %d, config->channel_mask %#x", __func__, source, config->channel_mask);
Aalique Grahame22e49102018-12-18 14:23:57 -08008344 if (source == AUDIO_SOURCE_VOICE_UPLINK ||
8345 source == AUDIO_SOURCE_VOICE_DOWNLINK) {
8346 /* Force channel config requested to mono if incall
8347 record is being requested for only uplink/downlink */
8348 if (config->channel_mask != AUDIO_CHANNEL_IN_MONO) {
8349 config->channel_mask = AUDIO_CHANNEL_IN_MONO;
8350 ret = -EINVAL;
8351 goto err_open;
8352 }
8353 }
8354
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008355 if (is_usb_dev && may_use_hifi_record) {
8356 /* HiFi record selects an appropriate format, channel, rate combo
8357 depending on sink capabilities*/
8358 ret = read_usb_sup_params_and_compare(false /*is_playback*/,
8359 &config->format,
8360 &in->supported_formats[0],
8361 MAX_SUPPORTED_FORMATS,
8362 &config->channel_mask,
8363 &in->supported_channel_masks[0],
8364 MAX_SUPPORTED_CHANNEL_MASKS,
8365 &config->sample_rate,
8366 &in->supported_sample_rates[0],
8367 MAX_SUPPORTED_SAMPLE_RATES);
8368 if (ret != 0) {
8369 ret = -EINVAL;
8370 goto err_open;
8371 }
8372 channel_count = audio_channel_count_from_in_mask(config->channel_mask);
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008373 } else if (config->format == AUDIO_FORMAT_DEFAULT) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308374 config->format = AUDIO_FORMAT_PCM_16_BIT;
Surendar karkaaca3d082017-11-09 15:18:37 +05308375 } else if (property_get_bool("vendor.audio.capture.pcm.32bit.enable", false)
8376 && config->format == AUDIO_FORMAT_PCM_32_BIT) {
8377 in->config.format = PCM_FORMAT_S32_LE;
8378 in->bit_width = 32;
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308379 } else if ((config->format == AUDIO_FORMAT_PCM_FLOAT) ||
8380 (config->format == AUDIO_FORMAT_PCM_32_BIT) ||
8381 (config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED) ||
8382 (config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
8383 bool ret_error = false;
8384 in->bit_width = 24;
8385 /* 24 bit is restricted to UNPROCESSED source only,also format supported
8386 from HAL is 24_packed and 8_24
8387 *> In case of UNPROCESSED source, for 24 bit, if format requested is other than
8388 24_packed return error indicating supported format is 24_packed
8389 *> In case of any other source requesting 24 bit or float return error
8390 indicating format supported is 16 bit only.
8391
8392 on error flinger will retry with supported format passed
8393 */
8394 if ((source != AUDIO_SOURCE_UNPROCESSED) &&
8395 (source != AUDIO_SOURCE_CAMCORDER)) {
8396 config->format = AUDIO_FORMAT_PCM_16_BIT;
8397 if (config->sample_rate > 48000)
8398 config->sample_rate = 48000;
8399 ret_error = true;
Haynes Mathew George46740472017-10-27 18:40:12 -07008400 } else if (!(config->format == AUDIO_FORMAT_PCM_24_BIT_PACKED ||
8401 config->format == AUDIO_FORMAT_PCM_8_24_BIT)) {
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308402 config->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
8403 ret_error = true;
8404 }
8405
8406 if (ret_error) {
8407 ret = -EINVAL;
8408 goto err_open;
8409 }
8410 }
8411
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008412 in->channel_mask = config->channel_mask;
8413 in->format = config->format;
8414
8415 in->usecase = USECASE_AUDIO_RECORD;
Samyak Jain0aa07ab2019-04-04 14:36:32 +05308416
8417 if (in->source == AUDIO_SOURCE_FM_TUNER) {
8418 if(!get_usecase_from_list(adev, USECASE_AUDIO_RECORD_FM_VIRTUAL))
8419 in->usecase = USECASE_AUDIO_RECORD_FM_VIRTUAL;
8420 else {
8421 ret = -EINVAL;
8422 goto err_open;
8423 }
8424 }
8425
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008426 if (config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE &&
8427 (flags & AUDIO_INPUT_FLAG_FAST) != 0) {
8428 is_low_latency = true;
8429#if LOW_LATENCY_CAPTURE_USE_CASE
8430 in->usecase = USECASE_AUDIO_RECORD_LOW_LATENCY;
8431#endif
8432 in->realtime = may_use_noirq_mode(adev, in->usecase, in->flags);
Aalique Grahame22e49102018-12-18 14:23:57 -08008433 if (!in->realtime) {
8434 in->config = pcm_config_audio_capture;
8435 frame_size = audio_stream_in_frame_size(&in->stream);
8436 buffer_size = get_input_buffer_size(config->sample_rate,
8437 config->format,
8438 channel_count,
8439 is_low_latency);
8440 in->config.period_size = buffer_size / frame_size;
8441 in->config.rate = config->sample_rate;
8442 in->af_period_multiplier = 1;
8443 } else {
8444 // period size is left untouched for rt mode playback
8445 in->config = pcm_config_audio_capture_rt;
8446 in->af_period_multiplier = af_period_multiplier;
8447 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008448 }
8449
8450 if ((config->sample_rate == LOW_LATENCY_CAPTURE_SAMPLE_RATE) &&
8451 ((in->flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0)) {
8452 in->realtime = 0;
8453 in->usecase = USECASE_AUDIO_RECORD_MMAP;
8454 in->config = pcm_config_mmap_capture;
Haynes Mathew George46740472017-10-27 18:40:12 -07008455 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008456 in->stream.start = in_start;
8457 in->stream.stop = in_stop;
8458 in->stream.create_mmap_buffer = in_create_mmap_buffer;
8459 in->stream.get_mmap_position = in_get_mmap_position;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008460 ALOGV("%s: USECASE_AUDIO_RECORD_MMAP", __func__);
8461 } else if (in->realtime) {
8462 in->config = pcm_config_audio_capture_rt;
Haynes Mathew George46740472017-10-27 18:40:12 -07008463 in->config.format = pcm_format_from_audio_format(config->format);
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008464 in->af_period_multiplier = af_period_multiplier;
Haynes Mathew George46740472017-10-27 18:40:12 -07008465 } else if (is_usb_dev && may_use_hifi_record) {
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008466 in->usecase = USECASE_AUDIO_RECORD_HIFI;
8467 in->config = pcm_config_audio_capture;
8468 frame_size = audio_stream_in_frame_size(&in->stream);
8469 buffer_size = get_input_buffer_size(config->sample_rate,
8470 config->format,
8471 channel_count,
8472 false /*is_low_latency*/);
8473 in->config.period_size = buffer_size / frame_size;
8474 in->config.rate = config->sample_rate;
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008475 in->config.format = pcm_format_from_audio_format(config->format);
Karthikeyan Mani07faa602018-08-20 11:01:32 -07008476 switch (config->format) {
8477 case AUDIO_FORMAT_PCM_32_BIT:
8478 in->bit_width = 32;
8479 break;
8480 case AUDIO_FORMAT_PCM_24_BIT_PACKED:
8481 case AUDIO_FORMAT_PCM_8_24_BIT:
8482 in->bit_width = 24;
8483 break;
8484 default:
8485 in->bit_width = 16;
8486 }
Haynes Mathew George484e8d22017-07-31 18:55:17 -07008487 } else if ((in->device == AUDIO_DEVICE_IN_TELEPHONY_RX) ||
Dhanalakshmi Siddani0b1488e2016-09-06 12:58:42 +05308488 (in->device == AUDIO_DEVICE_IN_PROXY)) {
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008489 if (config->sample_rate == 0)
8490 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8491 if (config->sample_rate != 48000 && config->sample_rate != 16000 &&
8492 config->sample_rate != 8000) {
8493 config->sample_rate = AFE_PROXY_SAMPLING_RATE;
8494 ret = -EINVAL;
8495 goto err_open;
8496 }
8497 if (config->format == AUDIO_FORMAT_DEFAULT)
8498 config->format = AUDIO_FORMAT_PCM_16_BIT;
8499 if (config->format != AUDIO_FORMAT_PCM_16_BIT) {
8500 config->format = AUDIO_FORMAT_PCM_16_BIT;
8501 ret = -EINVAL;
8502 goto err_open;
8503 }
8504
8505 in->usecase = USECASE_AUDIO_RECORD_AFE_PROXY;
8506 in->config = pcm_config_afe_proxy_record;
Ravi Kumar Alamanda060bc5a2014-09-05 13:51:35 -07008507 in->config.rate = config->sample_rate;
Aalique Grahame22e49102018-12-18 14:23:57 -08008508 in->af_period_multiplier = 1;
8509 } else if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION &&
8510 in->flags & AUDIO_INPUT_FLAG_VOIP_TX &&
8511 (config->sample_rate == 8000 ||
8512 config->sample_rate == 16000 ||
8513 config->sample_rate == 32000 ||
8514 config->sample_rate == 48000) &&
8515 channel_count == 1) {
8516 in->usecase = USECASE_AUDIO_RECORD_VOIP;
8517 in->config = pcm_config_audio_capture;
8518 frame_size = audio_stream_in_frame_size(&in->stream);
8519 buffer_size = get_stream_buffer_size(VOIP_CAPTURE_PERIOD_DURATION_MSEC,
8520 config->sample_rate,
8521 config->format,
8522 channel_count, false /*is_low_latency*/);
8523 in->config.period_size = buffer_size / frame_size;
8524 in->config.period_count = VOIP_CAPTURE_PERIOD_COUNT;
8525 in->config.rate = config->sample_rate;
8526 in->af_period_multiplier = 1;
Haynes Mathew George46740472017-10-27 18:40:12 -07008527 } else {
Revathi Uddarajud2634032017-12-07 14:42:34 +05308528 int ret_val;
8529 pthread_mutex_lock(&adev->lock);
8530 ret_val = audio_extn_check_and_set_multichannel_usecase(adev,
8531 in, config, &channel_mask_updated);
8532 pthread_mutex_unlock(&adev->lock);
8533
8534 if (!ret_val) {
8535 if (channel_mask_updated == true) {
8536 ALOGD("%s: return error to retry with updated channel mask (%#x)",
8537 __func__, config->channel_mask);
8538 ret = -EINVAL;
8539 goto err_open;
8540 }
8541 ALOGD("%s: created multi-channel session succesfully",__func__);
8542 } else if (audio_extn_compr_cap_enabled() &&
8543 audio_extn_compr_cap_format_supported(config->format) &&
8544 (in->dev->mode != AUDIO_MODE_IN_COMMUNICATION)) {
8545 audio_extn_compr_cap_init(in);
8546 } else if (audio_extn_cin_applicable_stream(in)) {
8547 ret = audio_extn_cin_configure_input_stream(in);
8548 if (ret)
8549 goto err_open;
8550 } else {
8551 in->config = pcm_config_audio_capture;
8552 in->config.rate = config->sample_rate;
8553 in->config.format = pcm_format_from_audio_format(config->format);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308554 in->format = config->format;
8555 frame_size = audio_stream_in_frame_size(&in->stream);
8556 buffer_size = get_input_buffer_size(config->sample_rate,
Haynes Mathew George46740472017-10-27 18:40:12 -07008557 config->format,
8558 channel_count,
8559 is_low_latency);
Dieter Luecking5d57def2018-09-07 14:23:37 +02008560 /* prevent division-by-zero */
8561 if (frame_size == 0) {
8562 ALOGE("%s: Error frame_size==0", __func__);
8563 ret = -EINVAL;
8564 goto err_open;
8565 }
8566
Revathi Uddarajud2634032017-12-07 14:42:34 +05308567 in->config.period_size = buffer_size / frame_size;
Aalique Grahame22e49102018-12-18 14:23:57 -08008568 in->af_period_multiplier = 1;
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008569
Revathi Uddarajud2634032017-12-07 14:42:34 +05308570 if (in->source == AUDIO_SOURCE_VOICE_COMMUNICATION) {
8571 /* optionally use VOIP usecase depending on config(s) */
8572 ret = adev_update_voice_comm_input_stream(in, config);
8573 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008574
Revathi Uddarajud2634032017-12-07 14:42:34 +05308575 if (ret) {
8576 ALOGE("%s AUDIO_SOURCE_VOICE_COMMUNICATION invalid args", __func__);
8577 goto err_open;
8578 }
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008579 }
Samyak Jainc37062f2019-04-25 18:41:06 +05308580 if (audio_extn_is_concurrent_capture_enabled()) {
8581 /* Acquire lock to avoid two concurrent use cases initialized to
8582 same pcm record use case */
kunleiz28c73e72019-03-27 17:24:04 +08008583
Samyak Jainc37062f2019-04-25 18:41:06 +05308584 if (in->usecase == USECASE_AUDIO_RECORD) {
8585 pthread_mutex_lock(&adev->lock);
8586 if (!(adev->pcm_record_uc_state)) {
8587 ALOGV("%s: using USECASE_AUDIO_RECORD",__func__);
8588 adev->pcm_record_uc_state = 1;
8589 pthread_mutex_unlock(&adev->lock);
8590 } else {
8591 pthread_mutex_unlock(&adev->lock);
8592 /* Assign compress record use case for second record */
8593 in->usecase = USECASE_AUDIO_RECORD_COMPRESS2;
8594 in->flags |= AUDIO_INPUT_FLAG_COMPRESS;
8595 ALOGV("%s: overriding usecase with USECASE_AUDIO_RECORD_COMPRESS2 and appending compress flag", __func__);
8596 if (audio_extn_cin_applicable_stream(in)) {
8597 in->sample_rate = config->sample_rate;
8598 ret = audio_extn_cin_configure_input_stream(in);
8599 if (ret)
8600 goto err_open;
8601 }
8602 }
8603 }
kunleiz28c73e72019-03-27 17:24:04 +08008604 }
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008605 }
Aniket Kumar Lata23d8cbf2019-04-10 19:54:46 -07008606
8607 in->config.channels = channel_count;
8608 in->sample_rate = in->config.rate;
8609
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308610 audio_extn_utils_update_stream_input_app_type_cfg(adev->platform,
8611 &adev->streams_input_cfg_list,
Haynes Mathew George4ffef292017-11-21 15:08:02 -08008612 devices, flags, in->format,
8613 in->sample_rate, in->bit_width,
8614 in->profile, &in->app_type_cfg);
Naresh Tanniru04f71882018-06-26 17:46:22 +05308615 register_format(in->format, in->supported_formats);
8616 register_channel_mask(in->channel_mask, in->supported_channel_masks);
8617 register_sample_rate(in->sample_rate, in->supported_sample_rates);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308618
Aalique Grahame22e49102018-12-18 14:23:57 -08008619 in->error_log = error_log_create(
8620 ERROR_LOG_ENTRIES,
8621 1000000000 /* aggregate consecutive identical errors within one second */);
8622
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008623 /* This stream could be for sound trigger lab,
8624 get sound trigger pcm if present */
8625 audio_extn_sound_trigger_check_and_get_session(in);
8626
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308627 lock_input_stream(in);
8628 audio_extn_snd_mon_register_listener(in, in_snd_mon_cb);
8629 pthread_mutex_lock(&adev->lock);
8630 in->card_status = adev->card_status;
8631 pthread_mutex_unlock(&adev->lock);
8632 pthread_mutex_unlock(&in->lock);
8633
Aalique Grahame22e49102018-12-18 14:23:57 -08008634 stream_app_type_cfg_init(&in->app_type_cfg);
8635
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008636 *stream_in = &in->stream;
Derek Chenf939fb72018-11-13 13:34:41 -08008637
8638 streams_input_ctxt_t *in_ctxt = (streams_input_ctxt_t *)
8639 calloc(1, sizeof(streams_input_ctxt_t));
8640 if (in_ctxt == NULL) {
8641 ALOGE("%s fail to allocate input ctxt", __func__);
8642 ret = -ENOMEM;
8643 goto err_open;
8644 }
8645 in_ctxt->input = in;
8646
8647 pthread_mutex_lock(&adev->lock);
8648 list_add_tail(&adev->active_inputs_list, &in_ctxt->list);
8649 pthread_mutex_unlock(&adev->lock);
8650
Eric Laurent994a6932013-07-17 11:51:42 -07008651 ALOGV("%s: exit", __func__);
Ravi Kumar Alamandafae42112013-11-07 23:31:54 -08008652 return ret;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008653
8654err_open:
Samyak Jainc37062f2019-04-25 18:41:06 +05308655 if (in->usecase == USECASE_AUDIO_RECORD) {
8656 pthread_mutex_lock(&adev->lock);
8657 adev->pcm_record_uc_state = 0;
8658 pthread_mutex_unlock(&adev->lock);
8659 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008660 free(in);
8661 *stream_in = NULL;
8662 return ret;
8663}
8664
8665static void adev_close_input_stream(struct audio_hw_device *dev,
8666 struct audio_stream_in *stream)
8667{
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008668 int ret;
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008669 struct stream_in *in = (struct stream_in *)stream;
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008670 struct audio_device *adev = (struct audio_device *)dev;
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308671
Sidipotu Ashokf43018c2014-05-02 16:21:50 +05308672 ALOGD("%s: enter:stream_handle(%p)",__func__, in);
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08008673
kunleiz70e57612018-12-28 17:50:23 +08008674 /* must deregister from sndmonitor first to prevent races
8675 * between the callback and close_stream
8676 */
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308677 audio_extn_snd_mon_unregister_listener(stream);
8678
kunleiz70e57612018-12-28 17:50:23 +08008679 /* Disable echo reference if there are no active input, hfp call
8680 * and sound trigger while closing input stream
8681 */
8682 if (!adev->active_input &&
8683 !audio_extn_hfp_is_active(adev) &&
8684 !audio_extn_sound_trigger_check_ec_ref_enable())
kunleiz8c93ce62018-11-29 15:04:56 +08008685 platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
kunleiz70e57612018-12-28 17:50:23 +08008686 else
8687 audio_extn_sound_trigger_update_ec_ref_status(false);
Venkata Narendra Kumar Gutta1bbbf542014-09-04 19:11:25 +05308688
Pallavid7c7a272018-01-16 11:22:55 +05308689 if (in == NULL) {
8690 ALOGE("%s: audio_stream_in ptr is NULL", __func__);
8691 return;
8692 }
Weiyin Jiang2995f662019-04-17 14:25:12 +08008693 error_log_destroy(in->error_log);
8694 in->error_log = NULL;
8695
Pallavid7c7a272018-01-16 11:22:55 +05308696
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008697 if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308698 pthread_mutex_lock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008699 ret = voice_extn_compress_voip_close_input_stream(&stream->common);
Venkata Narendra Kumar Gutta91812142014-08-11 18:20:49 +05308700 pthread_mutex_unlock(&adev->lock);
Narsinga Rao Chella05573b72013-11-15 15:21:40 -08008701 if (ret != 0)
8702 ALOGE("%s: Compress voip input cannot be closed, error:%d",
8703 __func__, ret);
8704 } else
8705 in_standby(&stream->common);
8706
Revathi Uddarajud2634032017-12-07 14:42:34 +05308707 pthread_mutex_lock(&adev->lock);
Samyak Jain15fda662018-12-18 16:40:52 +05308708 if (in->usecase == USECASE_AUDIO_RECORD) {
8709 adev->pcm_record_uc_state = 0;
8710 }
8711
Shiv Maliyappanahalli5a10aea2015-07-02 10:36:23 -07008712 if (audio_extn_ssr_get_stream() == in) {
Apoorv Raghuvanshi6178a3f2013-10-19 12:38:54 -07008713 audio_extn_ssr_deinit();
8714 }
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008715
Garmond Leunge2433c32017-09-28 21:51:22 -07008716 if (audio_extn_ffv_get_stream() == in) {
8717 audio_extn_ffv_stream_deinit();
8718 }
8719
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308720 if (audio_extn_compr_cap_enabled() &&
Mingming Yine62d7842013-10-25 16:26:03 -07008721 audio_extn_compr_cap_format_supported(in->config.format))
8722 audio_extn_compr_cap_deinit();
Dhanalakshmi Siddani74cf00b2016-12-02 13:55:57 +05308723
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308724 if (audio_extn_cin_attached_usecase(in->usecase))
8725 audio_extn_cin_close_input_stream(in);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008726
Mingming Yinfd7607b2016-01-22 12:48:44 -08008727 if (in->is_st_session) {
8728 ALOGV("%s: sound trigger pcm stop lab", __func__);
8729 audio_extn_sound_trigger_stop_lab(in);
8730 }
Derek Chenf939fb72018-11-13 13:34:41 -08008731 streams_input_ctxt_t *in_ctxt = in_get_stream(adev, in->capture_handle);
8732 if (in_ctxt != NULL) {
8733 list_remove(&in_ctxt->list);
8734 free(in_ctxt);
8735 } else {
8736 ALOGW("%s, input stream already closed", __func__);
8737 }
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008738 free(stream);
Revathi Uddarajud2634032017-12-07 14:42:34 +05308739 pthread_mutex_unlock(&adev->lock);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008740 return;
8741}
8742
Aalique Grahame22e49102018-12-18 14:23:57 -08008743/* verifies input and output devices and their capabilities.
8744 *
8745 * This verification is required when enabling extended bit-depth or
8746 * sampling rates, as not all qcom products support it.
8747 *
8748 * Suitable for calling only on initialization such as adev_open().
8749 * It fills the audio_device use_case_table[] array.
8750 *
8751 * Has a side-effect that it needs to configure audio routing / devices
8752 * in order to power up the devices and read the device parameters.
8753 * It does not acquire any hw device lock. Should restore the devices
8754 * back to "normal state" upon completion.
8755 */
8756static int adev_verify_devices(struct audio_device *adev)
8757{
8758 /* enumeration is a bit difficult because one really wants to pull
8759 * the use_case, device id, etc from the hidden pcm_device_table[].
8760 * In this case there are the following use cases and device ids.
8761 *
8762 * [USECASE_AUDIO_PLAYBACK_DEEP_BUFFER] = {0, 0},
8763 * [USECASE_AUDIO_PLAYBACK_LOW_LATENCY] = {15, 15},
8764 * [USECASE_AUDIO_PLAYBACK_HIFI] = {1, 1},
8765 * [USECASE_AUDIO_PLAYBACK_OFFLOAD] = {9, 9},
8766 * [USECASE_AUDIO_RECORD] = {0, 0},
8767 * [USECASE_AUDIO_RECORD_LOW_LATENCY] = {15, 15},
8768 * [USECASE_VOICE_CALL] = {2, 2},
8769 *
8770 * USECASE_AUDIO_PLAYBACK_OFFLOAD, USECASE_AUDIO_PLAYBACK_HIFI omitted.
8771 * USECASE_VOICE_CALL omitted, but possible for either input or output.
8772 */
8773
8774 /* should be the usecases enabled in adev_open_input_stream() */
8775 static const int test_in_usecases[] = {
8776 USECASE_AUDIO_RECORD,
8777 USECASE_AUDIO_RECORD_LOW_LATENCY, /* does not appear to be used */
8778 };
8779 /* should be the usecases enabled in adev_open_output_stream()*/
8780 static const int test_out_usecases[] = {
8781 USECASE_AUDIO_PLAYBACK_DEEP_BUFFER,
8782 USECASE_AUDIO_PLAYBACK_LOW_LATENCY,
8783 };
8784 static const usecase_type_t usecase_type_by_dir[] = {
8785 PCM_PLAYBACK,
8786 PCM_CAPTURE,
8787 };
8788 static const unsigned flags_by_dir[] = {
8789 PCM_OUT,
8790 PCM_IN,
8791 };
8792
8793 size_t i;
8794 unsigned dir;
8795 const unsigned card_id = adev->snd_card;
8796
8797 for (dir = 0; dir < 2; ++dir) {
8798 const usecase_type_t usecase_type = usecase_type_by_dir[dir];
8799 const unsigned flags_dir = flags_by_dir[dir];
8800 const size_t testsize =
8801 dir ? ARRAY_SIZE(test_in_usecases) : ARRAY_SIZE(test_out_usecases);
8802 const int *testcases =
8803 dir ? test_in_usecases : test_out_usecases;
8804 const audio_devices_t audio_device =
8805 dir ? AUDIO_DEVICE_IN_BUILTIN_MIC : AUDIO_DEVICE_OUT_SPEAKER;
8806
8807 for (i = 0; i < testsize; ++i) {
8808 const audio_usecase_t audio_usecase = testcases[i];
8809 int device_id;
8810 struct pcm_params **pparams;
8811 struct stream_out out;
8812 struct stream_in in;
8813 struct audio_usecase uc_info;
8814 int retval;
8815
8816 pparams = &adev->use_case_table[audio_usecase];
8817 pcm_params_free(*pparams); /* can accept null input */
8818 *pparams = NULL;
8819
8820 /* find the device ID for the use case (signed, for error) */
8821 device_id = platform_get_pcm_device_id(audio_usecase, usecase_type);
8822 if (device_id < 0)
8823 continue;
8824
8825 /* prepare structures for device probing */
8826 memset(&uc_info, 0, sizeof(uc_info));
8827 uc_info.id = audio_usecase;
8828 uc_info.type = usecase_type;
8829 if (dir) {
8830 adev->active_input = &in;
8831 memset(&in, 0, sizeof(in));
8832 in.device = audio_device;
8833 in.source = AUDIO_SOURCE_VOICE_COMMUNICATION;
8834 uc_info.stream.in = &in;
8835 } else {
8836 adev->active_input = NULL;
8837 }
8838 memset(&out, 0, sizeof(out));
8839 out.devices = audio_device; /* only field needed in select_devices */
8840 uc_info.stream.out = &out;
8841 uc_info.devices = audio_device;
8842 uc_info.in_snd_device = SND_DEVICE_NONE;
8843 uc_info.out_snd_device = SND_DEVICE_NONE;
8844 list_add_tail(&adev->usecase_list, &uc_info.list);
8845
8846 /* select device - similar to start_(in/out)put_stream() */
8847 retval = select_devices(adev, audio_usecase);
8848 if (retval >= 0) {
8849 *pparams = pcm_params_get(card_id, device_id, flags_dir);
8850#if LOG_NDEBUG == 0
Aalique Grahame203bee02019-03-13 17:49:36 -07008851 char info[512]; /* for possible debug info */
Aalique Grahame22e49102018-12-18 14:23:57 -08008852 if (*pparams) {
8853 ALOGV("%s: (%s) card %d device %d", __func__,
8854 dir ? "input" : "output", card_id, device_id);
8855 pcm_params_to_string(*pparams, info, ARRAY_SIZE(info));
8856 } else {
8857 ALOGV("%s: cannot locate card %d device %d", __func__, card_id, device_id);
8858 }
8859#endif
8860 }
8861
8862 /* deselect device - similar to stop_(in/out)put_stream() */
8863 /* 1. Get and set stream specific mixer controls */
8864 retval = disable_audio_route(adev, &uc_info);
8865 /* 2. Disable the rx device */
8866 retval = disable_snd_device(adev,
8867 dir ? uc_info.in_snd_device : uc_info.out_snd_device);
8868 list_remove(&uc_info.list);
8869 }
8870 }
8871 adev->active_input = NULL; /* restore adev state */
8872 return 0;
8873}
8874
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308875int adev_create_audio_patch(struct audio_hw_device *dev,
8876 unsigned int num_sources,
8877 const struct audio_port_config *sources,
8878 unsigned int num_sinks,
8879 const struct audio_port_config *sinks,
8880 audio_patch_handle_t *handle)
8881{
Derek Chenf939fb72018-11-13 13:34:41 -08008882 int ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308883
Derek Chenf939fb72018-11-13 13:34:41 -08008884 ret = audio_extn_hw_loopback_create_audio_patch(dev,
8885 num_sources,
8886 sources,
8887 num_sinks,
8888 sinks,
8889 handle);
8890 ret |= audio_extn_auto_hal_create_audio_patch(dev,
8891 num_sources,
8892 sources,
8893 num_sinks,
8894 sinks,
8895 handle);
8896 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308897}
8898
8899int adev_release_audio_patch(struct audio_hw_device *dev,
8900 audio_patch_handle_t handle)
8901{
Derek Chenf939fb72018-11-13 13:34:41 -08008902 int ret;
8903
8904 ret = audio_extn_hw_loopback_release_audio_patch(dev, handle);
8905 ret |= audio_extn_auto_hal_release_audio_patch(dev, handle);
8906 return ret;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05308907}
8908
8909int adev_get_audio_port(struct audio_hw_device *dev, struct audio_port *config)
8910{
8911 return audio_extn_hw_loopback_get_audio_port(dev, config);
8912}
8913
8914int adev_set_audio_port_config(struct audio_hw_device *dev,
8915 const struct audio_port_config *config)
8916{
8917 return audio_extn_hw_loopback_set_audio_port_config(dev, config);
8918}
8919
Ravi Kumar Alamandabdf14162014-09-05 16:14:17 -07008920static int adev_dump(const audio_hw_device_t *device __unused,
8921 int fd __unused)
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008922{
8923 return 0;
8924}
8925
8926static int adev_close(hw_device_t *device)
8927{
Aalique Grahame22e49102018-12-18 14:23:57 -08008928 size_t i;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008929 struct audio_device *adev = (struct audio_device *)device;
Kiran Kandi910e1862013-10-29 13:29:42 -07008930
8931 if (!adev)
8932 return 0;
8933
8934 pthread_mutex_lock(&adev_init_lock);
8935
8936 if ((--audio_device_ref_count) == 0) {
Sujin Panicker390724d2019-04-26 10:43:36 +05308937 if (audio_extn_spkr_prot_is_enabled())
8938 audio_extn_spkr_prot_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308939 audio_extn_snd_mon_unregister_listener(adev);
Ravi Kumar Alamanda8fa6b192014-09-09 16:06:42 -07008940 audio_extn_sound_trigger_deinit(adev);
Kiran Kandide144c82013-11-20 15:58:32 -08008941 audio_extn_listen_deinit(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08008942 audio_extn_qdsp_deinit();
Aalique Grahame22e49102018-12-18 14:23:57 -08008943 audio_extn_extspk_deinit(adev->extspk);
Dhananjay Kumard6d32152016-10-13 16:11:03 +05308944 audio_extn_utils_release_streams_cfg_lists(
8945 &adev->streams_output_cfg_list,
8946 &adev->streams_input_cfg_list);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05308947 if (audio_extn_qaf_is_enabled())
8948 audio_extn_qaf_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008949 audio_route_free(adev->audio_route);
Weiyin Jiangfa65d3e2019-03-05 23:39:45 +08008950 audio_extn_gef_deinit(adev);
Kiran Kandi910e1862013-10-29 13:29:42 -07008951 free(adev->snd_dev_ref_cnt);
8952 platform_deinit(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08008953 for (i = 0; i < ARRAY_SIZE(adev->use_case_table); ++i) {
8954 pcm_params_free(adev->use_case_table[i]);
8955 }
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07008956 if (adev->adm_deinit)
8957 adev->adm_deinit(adev->adm_data);
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05308958 qahwi_deinit(device);
Ben Rombergerd771a7c2017-02-22 18:05:17 -08008959 audio_extn_adsp_hdlr_deinit();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308960 audio_extn_snd_mon_deinit();
Siddartha Shaik44dd7702017-06-14 12:13:25 +05308961 audio_extn_hw_loopback_deinit(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07008962 audio_extn_ffv_deinit();
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05308963 if (adev->device_cfg_params) {
8964 free(adev->device_cfg_params);
8965 adev->device_cfg_params = NULL;
8966 }
Derek Chend2530072014-11-24 12:39:14 -08008967 if(adev->ext_hw_plugin)
8968 audio_extn_ext_hw_plugin_deinit(adev->ext_hw_plugin);
Derek Chenae7b0342019-02-08 15:17:04 -08008969 audio_extn_auto_hal_deinit();
Kiran Kandi910e1862013-10-29 13:29:42 -07008970 free(device);
8971 adev = NULL;
8972 }
8973 pthread_mutex_unlock(&adev_init_lock);
Vatsal Buchac09ae062018-11-14 13:25:08 +05308974 enable_gcov();
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08008975 return 0;
8976}
8977
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008978/* This returns 1 if the input parameter looks at all plausible as a low latency period size,
8979 * or 0 otherwise. A return value of 1 doesn't mean the value is guaranteed to work,
8980 * just that it _might_ work.
8981 */
8982static int period_size_is_plausible_for_low_latency(int period_size)
8983{
8984 switch (period_size) {
8985 case 160:
Ravi Kumar Alamanda474de5a2015-06-25 20:08:01 -07008986 case 192:
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07008987 case 240:
8988 case 320:
8989 case 480:
8990 return 1;
8991 default:
8992 return 0;
8993 }
8994}
8995
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05308996static void adev_snd_mon_cb(void *cookie, struct str_parms *parms)
8997{
8998 bool is_snd_card_status = false;
8999 bool is_ext_device_status = false;
9000 char value[32];
9001 int card = -1;
9002 card_status_t status;
9003
9004 if (cookie != adev || !parms)
9005 return;
9006
9007 if (!parse_snd_card_status(parms, &card, &status)) {
9008 is_snd_card_status = true;
9009 } else if (0 < str_parms_get_str(parms, "ext_audio_device", value, sizeof(value))) {
9010 is_ext_device_status = true;
9011 } else {
9012 // not a valid event
9013 return;
9014 }
9015
9016 pthread_mutex_lock(&adev->lock);
9017 if (card == adev->snd_card || is_ext_device_status) {
9018 if (is_snd_card_status && adev->card_status != status) {
9019 adev->card_status = status;
9020 platform_snd_card_update(adev->platform, status);
9021 audio_extn_fm_set_parameters(adev, parms);
9022 } else if (is_ext_device_status) {
9023 platform_set_parameters(adev->platform, parms);
9024 }
9025 }
9026 pthread_mutex_unlock(&adev->lock);
9027 return;
9028}
9029
Chaithanya Krishna Bacharaju69d2e4c2017-05-26 18:22:46 +05309030/* out and adev lock held */
9031static int check_a2dp_restore_l(struct audio_device *adev, struct stream_out *out, bool restore)
9032{
9033 struct audio_usecase *uc_info;
9034 float left_p;
9035 float right_p;
9036 audio_devices_t devices;
9037
9038 uc_info = get_usecase_from_list(adev, out->usecase);
9039 if (uc_info == NULL) {
9040 ALOGE("%s: Could not find the usecase (%d) in the list",
9041 __func__, out->usecase);
9042 return -EINVAL;
9043 }
9044
9045 ALOGD("%s: enter: usecase(%d: %s)", __func__,
9046 out->usecase, use_case_table[out->usecase]);
9047
9048 if (restore) {
9049 // restore A2DP device for active usecases and unmute if required
9050 if ((out->devices & AUDIO_DEVICE_OUT_ALL_A2DP) &&
9051 (uc_info->out_snd_device != SND_DEVICE_OUT_BT_A2DP)) {
9052 ALOGD("%s: restoring A2dp and unmuting stream", __func__);
9053 select_devices(adev, uc_info->id);
9054 pthread_mutex_lock(&out->compr_mute_lock);
9055 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9056 (out->a2dp_compress_mute)) {
9057 out->a2dp_compress_mute = false;
9058 out_set_compr_volume(&out->stream, out->volume_l, out->volume_r);
9059 }
9060 pthread_mutex_unlock(&out->compr_mute_lock);
9061 }
9062 } else {
9063 // mute compress stream if suspended
9064 pthread_mutex_lock(&out->compr_mute_lock);
9065 if ((out->flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) &&
9066 (!out->a2dp_compress_mute)) {
9067 if (!out->standby) {
9068 ALOGD("%s: selecting speaker and muting stream", __func__);
9069 devices = out->devices;
9070 out->devices = AUDIO_DEVICE_OUT_SPEAKER;
9071 left_p = out->volume_l;
9072 right_p = out->volume_r;
9073 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9074 compress_pause(out->compr);
9075 out_set_compr_volume(&out->stream, (float)0, (float)0);
9076 out->a2dp_compress_mute = true;
9077 select_devices(adev, out->usecase);
9078 if (out->offload_state == OFFLOAD_STATE_PLAYING)
9079 compress_resume(out->compr);
9080 out->devices = devices;
9081 out->volume_l = left_p;
9082 out->volume_r = right_p;
9083 }
9084 }
9085 pthread_mutex_unlock(&out->compr_mute_lock);
9086 }
9087 ALOGV("%s: exit", __func__);
9088 return 0;
9089}
9090
9091int check_a2dp_restore(struct audio_device *adev, struct stream_out *out, bool restore)
9092{
9093 int ret = 0;
9094
9095 lock_output_stream(out);
9096 pthread_mutex_lock(&adev->lock);
9097
9098 ret = check_a2dp_restore_l(adev, out, restore);
9099
9100 pthread_mutex_unlock(&adev->lock);
9101 pthread_mutex_unlock(&out->lock);
9102 return ret;
9103}
9104
Haynes Mathew George01156f92018-04-13 15:29:54 -07009105void adev_on_battery_status_changed(bool charging)
9106{
9107 pthread_mutex_lock(&adev->lock);
9108 ALOGI("%s: battery status changed to %scharging", __func__, charging ? "" : "not ");
9109 adev->is_charging = charging;
Zhou Songc1088ea2018-06-12 00:17:29 +08009110 audio_extn_sound_trigger_update_battery_status(charging);
Haynes Mathew George01156f92018-04-13 15:29:54 -07009111 pthread_mutex_unlock(&adev->lock);
9112}
9113
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009114static int adev_open(const hw_module_t *module, const char *name,
9115 hw_device_t **device)
9116{
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309117 int ret;
Derek Chenf939fb72018-11-13 13:34:41 -08009118 char value[PROPERTY_VALUE_MAX] = {0};
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309119 char mixer_ctl_name[128] = {0};
9120 struct mixer_ctl *ctl = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309121
Ravi Kumar Alamanda75d924d2013-02-20 21:30:08 -08009122 ALOGD("%s: enter", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009123 if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
9124
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009125 pthread_mutex_lock(&adev_init_lock);
Kiran Kandi910e1862013-10-29 13:29:42 -07009126 if (audio_device_ref_count != 0){
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009127 *device = &adev->device.common;
Kiran Kandi910e1862013-10-29 13:29:42 -07009128 audio_device_ref_count++;
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009129 ALOGD("%s: returning existing instance of adev", __func__);
9130 ALOGD("%s: exit", __func__);
9131 pthread_mutex_unlock(&adev_init_lock);
9132 return 0;
9133 }
9134
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009135 adev = calloc(1, sizeof(struct audio_device));
9136
Haynes Mathew Georgeb51ceb12014-06-30 13:56:18 -07009137 if (!adev) {
9138 pthread_mutex_unlock(&adev_init_lock);
9139 return -ENOMEM;
9140 }
9141
Ravi Kumar Alamanda40703102014-04-24 10:34:41 -07009142 pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
9143
Weiyin Jiange6ce6312019-01-28 18:28:22 +08009144 // register audio ext hidl at the earliest
9145 audio_extn_hidl_init();
Revathi Uddaraju1eac8b02017-05-18 17:13:33 +05309146#ifdef DYNAMIC_LOG_ENABLED
9147 register_for_dynamic_logging("hal");
9148#endif
9149
Derek Chenf939fb72018-11-13 13:34:41 -08009150 /* default audio HAL major version */
9151 uint32_t maj_version = 2;
9152 if(property_get("vendor.audio.hal.maj.version", value, NULL))
9153 maj_version = atoi(value);
9154
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009155 adev->device.common.tag = HARDWARE_DEVICE_TAG;
Derek Chenf939fb72018-11-13 13:34:41 -08009156 adev->device.common.version = HARDWARE_DEVICE_API_VERSION(maj_version, 0);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009157 adev->device.common.module = (struct hw_module_t *)module;
9158 adev->device.common.close = adev_close;
9159
9160 adev->device.init_check = adev_init_check;
9161 adev->device.set_voice_volume = adev_set_voice_volume;
9162 adev->device.set_master_volume = adev_set_master_volume;
9163 adev->device.get_master_volume = adev_get_master_volume;
9164 adev->device.set_master_mute = adev_set_master_mute;
9165 adev->device.get_master_mute = adev_get_master_mute;
9166 adev->device.set_mode = adev_set_mode;
9167 adev->device.set_mic_mute = adev_set_mic_mute;
9168 adev->device.get_mic_mute = adev_get_mic_mute;
9169 adev->device.set_parameters = adev_set_parameters;
9170 adev->device.get_parameters = adev_get_parameters;
9171 adev->device.get_input_buffer_size = adev_get_input_buffer_size;
9172 adev->device.open_output_stream = adev_open_output_stream;
9173 adev->device.close_output_stream = adev_close_output_stream;
9174 adev->device.open_input_stream = adev_open_input_stream;
9175 adev->device.close_input_stream = adev_close_input_stream;
Siddartha Shaik31b530e2017-05-19 15:26:33 +05309176 adev->device.create_audio_patch = adev_create_audio_patch;
9177 adev->device.release_audio_patch = adev_release_audio_patch;
9178 adev->device.get_audio_port = adev_get_audio_port;
9179 adev->device.set_audio_port_config = adev_set_audio_port_config;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009180 adev->device.dump = adev_dump;
Naresh Tannirudcb47c52018-06-25 16:23:32 +05309181 adev->device.get_microphones = adev_get_microphones;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009182
9183 /* Set the default route before the PCM stream is opened */
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009184 adev->mode = AUDIO_MODE_NORMAL;
Eric Laurentc8400632013-02-14 19:04:54 -08009185 adev->active_input = NULL;
Ravi Kumar Alamanda096c87f2013-02-28 20:54:57 -08009186 adev->primary_output = NULL;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009187 adev->out_device = AUDIO_DEVICE_NONE;
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009188 adev->bluetooth_nrec = true;
Ravi Kumar Alamandaf9967042013-02-14 19:35:14 -08009189 adev->acdb_settings = TTY_MODE_OFF;
vivek mehta344576a2016-04-12 18:56:03 -07009190 adev->allow_afe_proxy_usage = true;
Ashish Jain1b9b30c2017-05-18 20:57:40 +05309191 adev->bt_sco_on = false;
Eric Laurent07eeafd2013-10-06 12:52:49 -07009192 /* adev->cur_hdmi_channels = 0; by calloc() */
Eric Laurentb23d5282013-05-14 15:27:20 -07009193 adev->snd_dev_ref_cnt = calloc(SND_DEVICE_MAX, sizeof(int));
vivek mehtaae1018c2019-05-09 12:19:57 -07009194 /* Init audio and voice feature */
9195 audio_extn_feature_init();
9196 voice_extn_feature_init();
Shiv Maliyappanahalli34b585f2013-10-01 15:49:05 -07009197 voice_init(adev);
Ravi Kumar Alamanda3b1816c2013-02-27 23:01:21 -08009198 list_init(&adev->usecase_list);
Derek Chenf939fb72018-11-13 13:34:41 -08009199 list_init(&adev->active_inputs_list);
9200 list_init(&adev->active_outputs_list);
Krishnankutty Kolathappilly0b2de1c2014-02-14 14:45:49 -08009201 adev->cur_wfd_channels = 2;
Subhash Chandra Bose Naripeddy16ff4f82014-04-01 21:03:10 -07009202 adev->offload_usecases_state = 0;
Samyak Jain15fda662018-12-18 16:40:52 +05309203 adev->pcm_record_uc_state = 0;
Ashish Jain81eb2a82015-05-13 10:52:34 +05309204 adev->is_channel_status_set = false;
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309205 adev->perf_lock_opts[0] = 0x101;
9206 adev->perf_lock_opts[1] = 0x20E;
9207 adev->perf_lock_opts_size = 2;
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009208 adev->dsp_bit_width_enforce_mode = 0;
Aalique Grahame552b0832019-03-11 10:16:38 -07009209 adev->enable_hfp = false;
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309210 adev->use_old_pspd_mix_ctrl = false;
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009211 adev->adm_routing_changed = false;
Naresh Tanniru4c630392014-05-12 01:05:52 +05309212
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009213 /* Loads platform specific libraries dynamically */
Eric Laurentb23d5282013-05-14 15:27:20 -07009214 adev->platform = platform_init(adev);
9215 if (!adev->platform) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009216 pthread_mutex_destroy(&adev->lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009217 free(adev->snd_dev_ref_cnt);
9218 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009219 adev = NULL;
Eric Laurentb23d5282013-05-14 15:27:20 -07009220 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9221 *device = NULL;
Apoorv Raghuvanshi6e57d7e2013-12-16 16:02:45 -08009222 pthread_mutex_unlock(&adev_init_lock);
Eric Laurentb23d5282013-05-14 15:27:20 -07009223 return -EINVAL;
9224 }
Eric Laurentc4aef752013-09-12 17:45:53 -07009225
Aalique Grahame22e49102018-12-18 14:23:57 -08009226 adev->extspk = audio_extn_extspk_init(adev);
9227
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309228 if (audio_extn_qaf_is_enabled()) {
9229 ret = audio_extn_qaf_init(adev);
9230 if (ret < 0) {
Ben Romberger2684ad72018-06-04 12:41:39 -07009231 pthread_mutex_destroy(&adev->lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309232 free(adev);
Ben Romberger2684ad72018-06-04 12:41:39 -07009233 adev = NULL;
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309234 ALOGE("%s: Failed to init platform data, aborting.", __func__);
9235 *device = NULL;
9236 pthread_mutex_unlock(&adev_init_lock);
Lakshman Chaluvaraju22ba9f12016-09-12 11:42:10 +05309237 return ret;
9238 }
9239
9240 adev->device.open_output_stream = audio_extn_qaf_open_output_stream;
9241 adev->device.close_output_stream = audio_extn_qaf_close_output_stream;
9242 }
9243
Derek Chenae7b0342019-02-08 15:17:04 -08009244 audio_extn_auto_hal_init(adev);
Derek Chend2530072014-11-24 12:39:14 -08009245 adev->ext_hw_plugin = audio_extn_ext_hw_plugin_init(adev);
9246
Eric Laurentc4aef752013-09-12 17:45:53 -07009247 if (access(VISUALIZER_LIBRARY_PATH, R_OK) == 0) {
9248 adev->visualizer_lib = dlopen(VISUALIZER_LIBRARY_PATH, RTLD_NOW);
9249 if (adev->visualizer_lib == NULL) {
9250 ALOGE("%s: DLOPEN failed for %s", __func__, VISUALIZER_LIBRARY_PATH);
9251 } else {
9252 ALOGV("%s: DLOPEN successful for %s", __func__, VISUALIZER_LIBRARY_PATH);
9253 adev->visualizer_start_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009254 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009255 "visualizer_hal_start_output");
9256 adev->visualizer_stop_output =
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009257 (int (*)(audio_io_handle_t, int))dlsym(adev->visualizer_lib,
Eric Laurentc4aef752013-09-12 17:45:53 -07009258 "visualizer_hal_stop_output");
9259 }
9260 }
Dhanalakshmi Siddani21be3ac2016-12-29 14:31:08 +05309261 audio_extn_init(adev);
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009262 voice_extn_init(adev);
Apoorv Raghuvanshi84fa2fe2013-12-04 11:57:47 -08009263 audio_extn_listen_init(adev, adev->snd_card);
Weiyin Jiangaa80acd2016-09-21 16:42:11 +08009264 audio_extn_gef_init(adev);
Siddartha Shaik44dd7702017-06-14 12:13:25 +05309265 audio_extn_hw_loopback_init(adev);
Garmond Leunge2433c32017-09-28 21:51:22 -07009266 audio_extn_ffv_init(adev);
Eric Laurentc4aef752013-09-12 17:45:53 -07009267
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009268 if (access(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, R_OK) == 0) {
9269 adev->offload_effects_lib = dlopen(OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH, RTLD_NOW);
9270 if (adev->offload_effects_lib == NULL) {
9271 ALOGE("%s: DLOPEN failed for %s", __func__,
9272 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9273 } else {
9274 ALOGV("%s: DLOPEN successful for %s", __func__,
9275 OFFLOAD_EFFECTS_BUNDLE_LIBRARY_PATH);
9276 adev->offload_effects_start_output =
Ashish Jain5106d362016-05-11 19:23:33 +05309277 (int (*)(audio_io_handle_t, int, struct mixer *))dlsym(adev->offload_effects_lib,
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009278 "offload_effects_bundle_hal_start_output");
9279 adev->offload_effects_stop_output =
9280 (int (*)(audio_io_handle_t, int))dlsym(adev->offload_effects_lib,
9281 "offload_effects_bundle_hal_stop_output");
Jitendra Naruka1b6513f2014-11-22 19:34:13 -08009282 adev->offload_effects_set_hpx_state =
9283 (int (*)(bool))dlsym(adev->offload_effects_lib,
9284 "offload_effects_bundle_set_hpx_state");
Dhananjay Kumard68883d2015-09-04 13:39:26 +05309285 adev->offload_effects_get_parameters =
9286 (void (*)(struct str_parms *, struct str_parms *))
9287 dlsym(adev->offload_effects_lib,
9288 "offload_effects_bundle_get_parameters");
9289 adev->offload_effects_set_parameters =
9290 (void (*)(struct str_parms *))dlsym(adev->offload_effects_lib,
9291 "offload_effects_bundle_set_parameters");
Subhash Chandra Bose Naripeddy1d089162013-11-13 13:31:50 -08009292 }
9293 }
9294
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009295 if (access(ADM_LIBRARY_PATH, R_OK) == 0) {
9296 adev->adm_lib = dlopen(ADM_LIBRARY_PATH, RTLD_NOW);
9297 if (adev->adm_lib == NULL) {
9298 ALOGE("%s: DLOPEN failed for %s", __func__, ADM_LIBRARY_PATH);
9299 } else {
9300 ALOGV("%s: DLOPEN successful for %s", __func__, ADM_LIBRARY_PATH);
9301 adev->adm_init = (adm_init_t)
9302 dlsym(adev->adm_lib, "adm_init");
9303 adev->adm_deinit = (adm_deinit_t)
9304 dlsym(adev->adm_lib, "adm_deinit");
9305 adev->adm_register_input_stream = (adm_register_input_stream_t)
9306 dlsym(adev->adm_lib, "adm_register_input_stream");
9307 adev->adm_register_output_stream = (adm_register_output_stream_t)
9308 dlsym(adev->adm_lib, "adm_register_output_stream");
9309 adev->adm_deregister_stream = (adm_deregister_stream_t)
9310 dlsym(adev->adm_lib, "adm_deregister_stream");
9311 adev->adm_request_focus = (adm_request_focus_t)
9312 dlsym(adev->adm_lib, "adm_request_focus");
9313 adev->adm_abandon_focus = (adm_abandon_focus_t)
9314 dlsym(adev->adm_lib, "adm_abandon_focus");
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009315 adev->adm_set_config = (adm_set_config_t)
9316 dlsym(adev->adm_lib, "adm_set_config");
9317 adev->adm_request_focus_v2 = (adm_request_focus_v2_t)
9318 dlsym(adev->adm_lib, "adm_request_focus_v2");
9319 adev->adm_is_noirq_avail = (adm_is_noirq_avail_t)
9320 dlsym(adev->adm_lib, "adm_is_noirq_avail");
9321 adev->adm_on_routing_change = (adm_on_routing_change_t)
9322 dlsym(adev->adm_lib, "adm_on_routing_change");
Aniket Kumar Lata60586a92019-05-22 22:18:55 -07009323 adev->adm_request_focus_v2_1 = (adm_request_focus_v2_1_t)
9324 dlsym(adev->adm_lib, "adm_request_focus_v2_1");
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009325 }
9326 }
9327
Aalique Grahame22e49102018-12-18 14:23:57 -08009328 adev->enable_voicerx = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009329 adev->bt_wb_speech_enabled = false;
Zhou Song12c29502019-03-16 10:37:18 +08009330 adev->swb_speech_mode = SPEECH_MODE_INVALID;
Alexy Joseph5e4ccbc2017-02-21 14:20:12 -08009331 //initialize this to false for now,
9332 //this will be set to true through set param
9333 adev->vr_audio_mode_enabled = false;
Mingming Yin514a8bc2014-07-29 15:22:21 -07009334
Pradnya Chaphekar8a9dcd82014-09-09 09:49:10 -07009335 audio_extn_ds2_enable(adev);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009336 *device = &adev->device.common;
Aalique Grahame22e49102018-12-18 14:23:57 -08009337
9338 if (k_enable_extended_precision)
9339 adev_verify_devices(adev);
9340
Xiaojun Sang785b5da2017-08-03 15:52:29 +08009341 adev->dsp_bit_width_enforce_mode =
9342 adev_init_dsp_bit_width_enforce_mode(adev->mixer);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009343
Dhananjay Kumard6d32152016-10-13 16:11:03 +05309344 audio_extn_utils_update_streams_cfg_lists(adev->platform, adev->mixer,
9345 &adev->streams_output_cfg_list,
9346 &adev->streams_input_cfg_list);
Subhash Chandra Bose Naripeddy19dc03b2014-03-10 14:43:05 -07009347
Kiran Kandi910e1862013-10-29 13:29:42 -07009348 audio_device_ref_count++;
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009349
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009350 int trial;
Aalique Grahame22e49102018-12-18 14:23:57 -08009351 if ((property_get("vendor.audio_hal.period_size", value, NULL) > 0) ||
9352 (property_get("audio_hal.period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009353 trial = atoi(value);
9354 if (period_size_is_plausible_for_low_latency(trial)) {
9355 pcm_config_low_latency.period_size = trial;
9356 pcm_config_low_latency.start_threshold = trial / 4;
9357 pcm_config_low_latency.avail_min = trial / 4;
9358 configured_low_latency_capture_period_size = trial;
9359 }
9360 }
Aalique Grahame22e49102018-12-18 14:23:57 -08009361 if ((property_get("vendor.audio_hal.in_period_size", value, NULL) > 0) ||
9362 (property_get("audio_hal.in_period_size", value, NULL) > 0)) {
Ravi Kumar Alamandadc9bb152014-09-08 15:59:58 -07009363 trial = atoi(value);
9364 if (period_size_is_plausible_for_low_latency(trial)) {
9365 configured_low_latency_capture_period_size = trial;
9366 }
9367 }
9368
Vignesh Kulothungan7d374312018-02-21 17:12:00 -08009369 adev->mic_break_enabled = property_get_bool("vendor.audio.mic_break", false);
9370
Eric Laurent4b084132018-10-19 17:33:43 -07009371 adev->camera_orientation = CAMERA_DEFAULT;
9372
Aalique Grahame22e49102018-12-18 14:23:57 -08009373 if ((property_get("vendor.audio_hal.period_multiplier",value,NULL) > 0) ||
9374 (property_get("audio_hal.period_multiplier",value,NULL) > 0)) {
Haynes Mathew George5beddd42016-06-27 18:33:40 -07009375 af_period_multiplier = atoi(value);
9376 if (af_period_multiplier < 0)
9377 af_period_multiplier = 2;
9378 else if (af_period_multiplier > 4)
9379 af_period_multiplier = 4;
9380
9381 ALOGV("new period_multiplier = %d", af_period_multiplier);
9382 }
9383
Arun Mirpurib1bec9c2019-01-29 16:42:45 -08009384 audio_extn_qdsp_init(adev->platform);
Aalique Grahame22e49102018-12-18 14:23:57 -08009385
Aniket Kumar Lata8fc67e62017-05-02 12:33:46 -07009386 adev->multi_offload_enable = property_get_bool("vendor.audio.offload.multiple.enabled", false);
Apoorv Raghuvanshi6e262842013-10-06 14:39:35 -07009387 pthread_mutex_unlock(&adev_init_lock);
9388
Ravi Kumar Alamanda8a0f9772015-06-15 10:35:19 -07009389 if (adev->adm_init)
9390 adev->adm_data = adev->adm_init();
9391
Dhananjay Kumaree4d2002016-10-25 18:02:58 +05309392 qahwi_init(*device);
Sudheer Papothifa9d2282015-09-17 01:53:25 +05309393 audio_extn_perf_lock_init();
Ben Rombergerd771a7c2017-02-22 18:05:17 -08009394 audio_extn_adsp_hdlr_init(adev->mixer);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309395
9396 audio_extn_snd_mon_init();
9397 pthread_mutex_lock(&adev->lock);
9398 audio_extn_snd_mon_register_listener(adev, adev_snd_mon_cb);
9399 adev->card_status = CARD_STATUS_ONLINE;
Haynes Mathew George01156f92018-04-13 15:29:54 -07009400 audio_extn_battery_properties_listener_init(adev_on_battery_status_changed);
9401 /*
9402 * if the battery state callback happens before charging can be queried,
9403 * it will be guarded with the adev->lock held in the cb function and so
9404 * the callback value will reflect the latest state
9405 */
9406 adev->is_charging = audio_extn_battery_properties_is_charging();
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309407 audio_extn_sound_trigger_init(adev); /* dependent on snd_mon_init() */
Zhou Songc1088ea2018-06-12 00:17:29 +08009408 audio_extn_sound_trigger_update_battery_status(adev->is_charging);
justinweng20fb6d82019-02-21 18:49:00 -07009409 audio_extn_audiozoom_init();
Zhou Songc1088ea2018-06-12 00:17:29 +08009410 pthread_mutex_unlock(&adev->lock);
Satish Babu Patakokilac3c5d432017-07-04 22:48:59 +05309411 /* Allocate memory for Device config params */
9412 adev->device_cfg_params = (struct audio_device_config_param*)
9413 calloc(platform_get_max_codec_backend(),
9414 sizeof(struct audio_device_config_param));
9415 if (adev->device_cfg_params == NULL)
9416 ALOGE("%s: Memory allocation failed for Device config params", __func__);
Dhananjay Kumare6293dd2017-05-25 17:25:30 +05309417
Dhanalakshmi Siddani20628c82019-01-27 17:31:09 +05309418 /*
9419 * Check if new PSPD matrix mixer control is supported. If not
9420 * supported, then set flag so that old mixer ctrl is sent while
9421 * sending pspd coefficients on older kernel version. Query mixer
9422 * control for default pcm id and channel value one.
9423 */
9424 snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
9425 "AudStr %d ChMixer Weight Ch %d", 0, 1);
9426
9427 ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
9428 if (!ctl) {
9429 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
9430 __func__, mixer_ctl_name);
9431 adev->use_old_pspd_mix_ctrl = true;
9432 }
9433
Eric Laurent994a6932013-07-17 11:51:42 -07009434 ALOGV("%s: exit", __func__);
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009435 return 0;
9436}
9437
9438static struct hw_module_methods_t hal_module_methods = {
9439 .open = adev_open,
9440};
9441
9442struct audio_module HAL_MODULE_INFO_SYM = {
9443 .common = {
9444 .tag = HARDWARE_MODULE_TAG,
9445 .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
9446 .hal_api_version = HARDWARE_HAL_API_VERSION,
9447 .id = AUDIO_HARDWARE_MODULE_ID,
9448 .name = "QCOM Audio HAL",
Duy Truongfae19622013-11-24 02:17:54 -08009449 .author = "The Linux Foundation",
Ravi Kumar Alamanda2dfba2b2013-01-17 16:50:22 -08009450 .methods = &hal_module_methods,
9451 },
9452};